经典ABR算法介绍:BBA (SIGCOMM ‘14) 设计与代码实现

前言

BBA(buffer-based algorithm)是DASH点播视频中最经典的ABR算法之一,也是基于缓冲区的(Buffer-based)ABR算法的代表作。BBA在稳定阶段仅基于播放器缓冲区水平来进行视频块的码率选择。本文基于BBA原论文和复现代码来介绍BBA的算法设计和实现逻辑。

BBA论文:A Buffer-Based Approach to Rate Adaptation: Evidence from a Large Video Streaming Service - SIGCOMM '14
BBA Python代码实现(来自Pensieve, SIGCOMM’ 17):https://github.com/hongzimao/pensieve/blob/master/test/bb.py

一些值得注意的点:

  • BBA的motivation来自于其团队之前的测量工作:当多个播放器竞争瓶颈链路时,ABR算法难以在应用层准确预测吞吐量。因此,BBA考虑仅基于播放器的缓冲区水平进行码率决策,不必依赖于吞吐量预测。
  • 在BBA之前,已有同时利用吞吐量预测和缓冲区信息的方法(之后的集大成者则为MPC, SIGCOMM '15),但BBA是第一个仅基于缓冲区进行决策的方法。
  • 实际上,BBA仅在视频流的稳定(steady-state)阶段才只使用缓冲区信息。这是因为启动(startup)阶段的缓冲区水平太低,还是需要依赖于吞吐量信息进行码率决策。类似地,同为Buffer-based类算法的BOLA和DYNAMIC也在起始阶段利用了视频块的吞吐量信息作为决策依据。
  • BBA有多个不同的变体:BBA-0(基础版本)、BBA-1(针对VBR视频)、BBA-2(针对启动阶段)。大部分后续工作进行复现和评估时,仅使用的是其基础版本BBA-0。
  • 尽管BBA-0非常简单,但其在真实场景中的码率和卡顿表现非常好(见Puffer的结果),甚至超越了后续的更为复杂的算法,比如MPC、Pensieve等。但BBA-0的问题在于其可能会导致非常频繁的码率切换。

BBA的不同变体

BBA分为三个不同的变体:(在之后的ABR研究工作中,主要对比的是BBA-0)

  • BBA-0:基础BBA算法,假设视频为CBR(constant bit-rate),通过确定reservoir和cushion(见下文),建立buffer与码率之间的线性映射关系
  • BBA-1:针对VBR(variable bit-rate)视频,将码率映射替换为视频块大小映射,即确定最小/最大视频块对应的buffer级别,建立线性决策函数,根据buffer水平和视频块大小决定所选码率(可能会导致频繁的码率切换)
  • BBA-2:针对启动阶段,其思想类似于CC的慢启动,基于上一视频块的吞吐量进行判断
    • BBA-2的码率选择:假设VBR视频块最高码率是该质量平均码率的2倍(e=2)
      • 视频块启动时,仅当视频块的下载速度是其播放速度的8倍以上(下载时间是视频块时长的1/8,即吞吐量是视频块码率的8倍以上),BBA-2才会提高码率级别
      • 当buffer填满cushion后,仅当视频块的下载速度是其播放速度的2倍以上,BBA-2才会提高码率级别
      • 该速率比值的阈值随buffer增长线性下降
    • BBA-2退出条件:满足以下二者之一时,退出启动阶段,切换至BBA-1
      • buffer开始下降
      • BBA-1所选码率高于BBA-2所选码率

除此之外,论文中也描述了BBA-Others来缓解Buffer-Based的码率切换问题(类似于BOLA-O的作用)。
BBA-Others针对码率切换,向前看若干个视频块的大小变化,减少高码率请求以避免频繁的码率切换。具体而言:

  • 若同一码率级别下一个小视频块后面跟随着若干个大视频块,BBA-1会为该小视频块选择较高的码率,但BBA-Others则不会请求更高的码率
  • 向前看的视频块数量等同于buffer中的视频块数量

可以将BBA-Others看作是介于BBA-0与BBA-1之间的版本,若其不向前看,则为BBA-1;无限向前看,则为BBA-0。

BBA-0核心思想

算法设计

BBA-0的核心算法非常简单,可以看作是一个从缓冲区水平到码率级别的线性映射函数,如下图所示:
image.png
BBA-0设置了reservoir和cushion两个参数作为缓冲区水平的阈值,其决策逻辑为:

  • 当缓冲区水平低于reservoir时,表明当前容易发生卡顿,则BBA-0选择最低码率级别(即图中的 R m i n R_{min} Rmin
  • 当缓冲区水平高于reservoir+cushion时,表明当前缓冲区足以避免卡顿发生,则BBA-0选择最高码率级别(即 R m a x R_{max} Rmax
  • 若缓冲区水平在这两个阈值之间,则BBA通过线性函数 f ( B ) f(B) f(B)确定缓冲区水平对应的码率级别

*之后的Buffer-based算法BOLA改进了BBA的线性决策函数,将其通过李雅普诺夫优化替换为了阶梯状的分段决策函数,详见:BOLA (INFOCOM ’16) 论文阅读笔记

代码实现

Pensieve的BBA复现代码中,可以看出BBA-0的核心逻辑非常简单,一共不到10行代码:

if buffer_size < RESEVOIR:
    bit_rate = 0
elif buffer_size >= RESEVOIR + CUSHION:
    bit_rate = A_DIM - 1
else:
    bit_rate = (A_DIM - 1) * (buffer_size - RESEVOIR) / float(CUSHION)

bit_rate = int(bit_rate)

其中,buffer_size为当前缓冲区水平(单位为秒),A_DIM为总共的码率基本数量,RESEVOIR和CUSHION对应BBA论文中的两个参数,分别设置为5s和10s(与MPC的实验设置相同)。需要注意的是,CUSHION这个参数最好不要设置得太小,否则可能会引发频繁的码率切换,BOLA论文中提到过这一点。
也就是说,若缓冲区低于5s,BBA-0选择最低码率;若缓冲区高于15s,BBA-0选择最高码率;若缓冲区在二者之间,则按照线性函数计算对应的码率级别(取整)。

猜你喜欢

转载自blog.csdn.net/LvGreat/article/details/131211119