webrtc QOS方法五.2(发送端帧率调整原理及实现流程)

    视频采集帧率是发送端能够发送的最大帧率,但是当码率太高冲击上行带宽时,或者编码性能跟不上采集帧率,发送端都会通过降帧率方式缓解这些问题。

    当码率太高冲击上行带宽时,通过MediaOptimization类调节帧率进而平滑码率;另外若使用webrtc自带VPX、openh264编码器,在编码器码控模块有接口配置是否掉帧调节码率功能。参见VideoCodecVP8/VideoCodecVP9/VideoCodecH264的frameDroppingOn参数定义。

    当编码性能跟不上采集帧率时,webrtc是通过直接掉帧方式解决,参见下面第三节《采集速度大于编码速度掉帧处理》描述。

一、MediaOptimization作用

MediaOptimization类作用是调节发送端码率,使用两种方式调节:

1、配置编码器输入帧率调整码率:编码器根据输入帧率和码率计算分配给每一帧的字节数。所以实时调节帧率,会调整码率。

2、编码前判断是否掉帧调整码率:实时监控编码后数据量,当检测到码率过高,通过主动掉帧方式降低码率,缓解网络冲击。

函数调用关系图如下:

webrtc QOS方法五.2(发送端帧率调整原理及实现流程)

二、MediaOptimization实现

1)计算编码帧率

  • 计算帧率

       每次编码前,调用MediaOptimization::DropFrame->MediaOptimization::ProcessIncomingFrameRate函数,将当前系统时间加入incoming_frame_times_队列。然后根据一段时间接收到的帧数和持续时间,计算输入视频的帧率。

webrtc QOS方法五.2(发送端帧率调整原理及实现流程)

  • 获取帧率

      每次编码前,调用VideoSender::UpdateEncoderParameters->MediaOptimization::InputFrameRate函数,更新encoder_params_,获取当前编码帧率,配置到编码器中。

2)判断是否掉帧

      判断是否掉帧在FrameDropper类里面实现。

webrtc QOS方法五.2(发送端帧率调整原理及实现流程)

  • 核心参数

       accumulator_max_:漏桶容积,其值为targetbps*kLeakyBucketSizeSeconds,随目标码率改变而改变;
       accumulator_:漏桶累积,漏桶累积字节数,Fill增加,Leak减少,最大值为targetbps*kAccumulatorCapBufferSizeSecs;
       drop_ratio_:丢帧率,指数滤波器,使丢帧率保持一个平滑的变化过程,每次Leak()后更新丢帧率;
       key_frame_ratio_:关键帧率,指数滤波器,使关键帧率保持一个平滑的变化过程,每次Fill()后更新;
      delta_frame_size_avg_kbits_:差分帧码率,指数滤波器,使关键帧率保持一个平滑的变化过程,每次Fill()后更新。

  • 核心函数

       FrameDropper::Fill      

H264EncoderImpl::Encode
->VCMEncodedFrameCallback::OnEncodedImage
->MediaOptimization::UpdateWithEncodedData
->FrameDropper::Fill

     当视频帧被编码后,MediaOptimization类会调用Fill()方法来填充漏桶。

     1、将大帧拆分为large_frame_accumulation_count_个小块,并不累加accumulator_;

     2、将小帧直接累计accumulator_。

     Fill()方法同时更新key_frame_ratio_和delta_frame_size_avg_kbits_,用以计算大帧拆分块数和大帧判断。 

      FrameDropper::Leak

VideoStreamEncoder::EncodeVideoFrame
->VideoSender::AddVideoFrame
->MediaOptimization::DropFrame
->FrameDropper::Leak

       Leak()操作按照编码器输入帧率的频率来执行,每次Leak的大小为targetbps/input_fps,每次Leak时需要判断是否需要累计Fill()方法拆分的块,进而更新drop_ratio_。drop_ratio_的更新遵循下列原则:
       当accumulator_ > 1.3f*accumulator_max_,drop_ratio_基数调整为0.8f*,提高丢帧率调整加速度;
       当accumulator_ < 1.3f*accumulator_max_,drop_ratio_基数调整为0.9f*,降低丢帧率调整加速度。

       FrameDropper::DropFrame

VideoStreamEncoder::EncodeVideoFrame
->VideoSender::AddVideoFrame
->MediaOptimization::DropFrame
->FrameDropper::DropFrame

      DropFrame()操作用来判断是否需要将输入到编码器的这一帧丢弃,其利用drop_ratio_来使丢帧率保持一个平滑的变化过程。

      当drop_ratio_.filtered() >= 0.5f时,表明连续丢弃多个帧(至少一个帧)

      当0.0f < drop_ratio_.filtered() < 0.5f时,表明多个帧才会丢弃一个帧。

webrtc QOS方法五.2(发送端帧率调整原理及实现流程)

三、采集速度大于编码速度掉帧处理

发送端若出现采集帧率大于编码帧率也会主动掉帧,这个掉帧在VideoStreamEncoder::EncodeTask::Run函数处理。

没有使用平滑算法,仅仅判断当前编码器是否空闲,空闲可以正常编码,不会丢帧,否则就会丢弃当前帧。

webrtc QOS方法五.2(发送端帧率调整原理及实现流程)

 

四、参考

https://www.jianshu.com/p/e2a9740b9877
http://www.enkichen.com/2017/07/29/webrtc-drop-frame/
https://www.freehacker.cn/media/webrtc-frame/

 

上一篇:5G NR协议栈SDAP、PDCP


下一篇:5G常见缩略词总结