自适应,是根据当前设备性能情况来动态的调整视频码率/帧率,为用户提供更好音视频体验感。
开启自适应
webrtc 默认开启自适应, googCpuOveruseDetection 默认为true ,可以通过设置此值为false 关闭自适应。
自适应策略
webrtc 提供了三种策略:
MAINTAIN_FRAMERATE:保帧率,降分辨率,该模式的使用场景为视频模式。
MAINTAIN_RESOLUTION: 保分辨率降帧率,使用场景为屏幕共享或者文档模式,对清晰度要求较高的场景。
BALANCED: 平衡帧率与分辨率。 默认关闭,需要通过 WebRTC-Video-BalancedDegradation 开启。
enum class DegradationPreference {
// Don't take any actions based on over-utilization signals. Not part of the
// web API.
DISABLED,
// On over-use, request lower resolution, possibly causing down-scaling.
MAINTAIN_FRAMERATE,
// On over-use, request lower frame rate, possibly causing frame drops.
MAINTAIN_RESOLUTION,
// Try to strike a "pleasing" balance between frame rate or resolution.
BALANCED,
};
自适应策略的设置
webrtc api 层提供了自适应策略的设置接口,通过设置 videotrack 的 ContentHint 属性就可以了。
enumclass ContentHint { kNone, kFluid, kDetailed, kText };
kFluid,表示编码器保持帧率,降低分辨率。用于视频模式,对视频流畅度要求较高,默认值kDetailed/kText, 表示编码器保持分辨率,降帧率。用于屏幕共享/文档模式,对清晰度要求较高场景
WebRtcVideoSendStream::GetDegradationPreference 函数中将 ContentHint 转换成 DegradationPreference。
自适应处理流程
1、视频采集设备,采集视频后交由IvdieoAdapter,根据设置的参数帧率,分辨率,进行预处理;
2、VideoAdapter 预处理后交由编码管理器,进行编码信息设置,设置完成后交由编码器进行编码;
3、在编码过程中,对CPU使用度,QP,像素,带宽进行检测。超过阈值认为过载,小于阈值则认为欠载;
4、将CPU使用度,QP,像素,带宽检测结果,统一转换为过载(kOveruse)/欠载(kUnderUse),根据 检测结果计算新的 分辨率/帧率值,具体由ResourceAdaptationProcess类处理;
5、由VideoStreamAdapter 将新的值,更新到其他模块。
CPU使用度(EncodeUsageResource)
“CPU使用度” 是指编码耗时 / 采集耗时,是一个比值。
- 当该比值越大时,表示编码跟不上采集,达到了编码器的性能瓶颈,需要对编码进行降级;
- 当该比值越小时,表示编码能力有富余,还可以进行编码升级,提供更好的视频质量。
由此可见,CPU使用度通过编码相对速率,来衡量当前的运行性能。这样做的好处有几个:
1、不与CPU硬件绑定,与硬件平台解耦
2、兼顾当前软件运行环境的影响,比如其他应用对CPU的消耗、操作系统对各进程资源的调度策略
初始值:
• high_encode_usage_threshold_percent:过载阀值,默认为 85.
• low_encode_usage_threshold_percent 欠载阀值,默认值为 42
• high_threshold_consecutive_count:过载的次数,默认为 2
•当编码器 is_hardware_accelerate,也就是使用硬件编码时,该阈值会进行调整,分别设置成150与200。
cpu使用度计算:
编码耗时 = 本帧编码结束时间 – 本帧编码开始时间;
编码采集间隔时间= 本帧编码开始时间 – 上一帧编码开始时间;
为了防止出现检测结果抖动,影响用户体验,需要对数据进行平滑处理,编码时长与采集间隔,都用了指数加权移动平均法(EWMA);
编码器占用率(usage_percent) = 编码时长/编码采集间隔时间。
Overuse
usage_percent 值大于 85 并且 usage_percent 连续超过两次,当被认定过载,编码降级
bool OveruseFrameDetector::IsOverusing(int usage_percent) {
RTC_DCHECK_RUN_ON(&task_checker_);
if (usage_percent >= options_.high_encode_usage_threshold_percent) {
++checks_above_threshold_;
} else {
checks_above_threshold_ = 0;
}
return checks_above_threshold_ >= options_.high_threshold_consecutive_count;
}
Underuse
欠载处理的 case 稍微就有点复杂了,目的是为了避免 Underuse 与 Overuse 频繁切换。
bool OveruseFrameDetector::IsUnderusing(int usage_percent, int64_t time_now) {
RTC_DCHECK_RUN_ON(&task_checker_);
int delay = in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_;
if (time_now < last_rampup_time_ms_ + delay)
return false;
return usage_percent < options_.low_encode_usage_threshold_percent;
}
kQuickRampUpDelayMs: 默认为 10s。
in_quick_rampup_: 标识是否需要快速上升,当上次是 Underuse 时,in_quick_rampup_才为 true。
current_rampup_delay_ms_:假设上次是 Underuse ,当前是 Overuse 状态,为了避免下次很快切换成 Underuse 状态,引入了这个变量。
T1: 上次 Underuse –> Overuse 的间隔
T2: 下次 Overuse –> Underuse 的间隔
当 T1 >= 40, T2 也就是 current_rampup_delayms 直接取 40,
当 T1 < 40 或者 Overuse 的总次数大于 4, T2 的范围在[80,240].
delay:用于计算当前时间与上次状态为 Underuse 时间间隔,防止状态切换过于频繁(不仅是 Underuse 与 Overuse,还要考虑 Underuse 与 Underuse)。
1、上次是 Underuse,此时 in_quick_rampup_为 true,需要快速上升,仅需当前时间与上次切换时间间隔大于 10s 就行了。
2、上次是 Overuse 或者其它,这时候 delay 就是 current_rampup_delay_ms_,current_rampup_delay_ms_的计算原理见上面的注解.
3、usage_percent值小于42 时,认为欠载,编码升级
QP检测(QualityScalerResource)
QP (QuantizationParameter 量化参数),相当于图像的复杂度。反应了视频的质量。QP过大,图像失真, 质量下降。QP过小,导致质量上升,码率上升。
QP检测目的是,让视频质量维持在可接受范围的前提下,调节整体视频表现,如分辨率、帧率,让视频达到最佳播放效果。
QP检测机制,只是利用QP分析结果对分辨率、帧率进行调节,并不对编码QP做直接调整。
当一系列图像的平均QP超过阈值时会调整分辨率(H264的合法范围是24~37),平均最高QP超过37要降分辨率,平均最小QP低于24要提高分辨率
•WebRTC-Video-QualityScalerSettings
•WebRTC-Video-QualityScaling 使用指数过滤,否则使用滑动窗口
默认每2秒检测一次
- 每帧编码结束后,都会上报QP
- 获取每帧的QP后,分别被添加到三个数据集 average_qp_、qp_smoother_high_、qp_smoother_low_ 中,在样本数据添加后立即完成滤波计算。
- average_qp_使用滑窗滤波rtc::MovingAverage,
- qp_smoother_high_和qp_smoother_low_ 使用指数滤波rtc::ExpFilter,均起到平滑数据的作用。
3.进行检测判断
- 采样点小于60, 认为采样点不足, kInsufficientSamples
- 当drop_rate大于 60%,认为视频质量不佳, kHighQp
- 当*avg_qp_high > 37,qp 过高 kHighQp
- 当*avg_qp_low <= 24,qp 过低 kLowQp
- 其他情况返回 kNormalQp
•为了方便后期处理 kHighQp 会转化成 kOveruse,kLowQp 转化成 kUnderuse。
像素检测(PixelLimitResource)
需要设置在 field_trial 才能开启,
WebRTC-PixelLimitResource/Enabled-518400(960*540)
- 启用一个5s 的定时器
- 获取最后一帧编码前视频帧的frame_size(宽*高)
- max_pixels_ 是从field_trial 读取而来
- current_pixels与max_pixels_ 进行比较
- 若current_pixels> max_pixels_ 则认为过载 kOveruse
- 若current_pixels<0.6*max_pixels_ 则认为欠载 kUnderuse
带宽变化检测(BandwidthQualityScalerReource)
•触发条件
1、保帧率,调整分辨率并且 编码配置允许质量调整(
is_quality_scaling_allowed=true)
2、属于QP提升,和QP互斥 !
encoder_info.is_qp_trusted.value_or(true)
3.每5秒检测一次
4.码率检测
•根据当前像素(最后一次更新的像素),从配置表中查询,获取最高,最低码率
- 当前码率(最后一次的码率)大于最高码码率95% 过载
- 当前码率(最后一次的码率)小于最低编码码率80% 欠载
执行欠载/过载过程
检测器处理生成了 kOveruse 和 kUnderuse 两种信号,再结合 DegradationPreference 值对像素或帧率进行调整
源码实现
作者:马龙飞鸽
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。