论文作者、摘要、关键词
论文解读
这篇文章提出了两种用于帧间编码加速的算法:自适应 CU 深度区间(Adaptive CU Depth Range ACUDR)和提前终止 CU 划分(Early Terminate ET)。
1. ACUDR
传统的 CU 划分算法是通过对所有的深度进行编码并计算代价,选择其中代价最小的策略作为最优策略,因此从深度为 0 (CU大小为 64x64,HEVC 中允许的最大 CU 大小)到深度为3(CU大小为 8x8, HEVC 中允许的最小 CU 大小)的情况都需要进行编码并计算代价,计算量非常大。
该算法考虑到相邻的 CU 具有很高的相关性,因此可以通过时域上(参考帧对应位置的 CU)和空域上(周围已编码的 CU)相关的 CU 来得到一个需要进行测试的深度区间,从而不必将所有的深度都尝试一遍,可以免去一些不必要的计算。
空域上的相关 CU 为当前 CU 的左侧 (L) 、上方 (U) 和左上方 (L-U) 的 CU;时域上的相关 CU 为前一个已编码帧的同位 CU (Col)。如下图(该文献的 Fig2):
通过利用这些已编码的相关 CU 的最优深度来计算得到预测深度
D
e
p
t
h
p
r
e
d
Depth_{pred}
Depthpred 。其计算公式如下:
D
e
p
t
h
p
r
e
d
=
∑
i
=
0
N
−
1
ω
i
⋅
δ
i
Depth_{pred}=\sum_{i=0}^{N-1}\omega_i \cdot \delta_i
Depthpred=i=0∑N−1ωi⋅δi
其中 N 是相关 CU 的数量,恒等于 4;
δ
i
\delta_i
δi 表示第 i 个相关 CU 的最优深度;
ω
i
\omega_i
ωi 表示权重:对于 L、Col、U 三个相关 CU,其权重取 0.3;对于 L-U, 其权重取 0.1。
之后根据 D e p t h p r e d Depth_{pred} Depthpred 的值判断深度区间:
- 若等于0,则深度范围为 [0,0](即只对 LCU 进行测试,不划分子 CU)
- 若大于0且小于 0.5 ,则深度范围为 [0,1]
- 若大于0.5且小于1.5,则深度范围为 [0,2]
- 若大于1.5且小于2.5,则深度范围为 [1,3]
- 若大于2.5,则深度范围为 [2,3]
该算法可能会错过实际上最优的深度,但在大多数情况下是能够选择到最优的 CU 的。如下表(该文献中的 Table 3):
2. ET
该文献的 ET 算法中提供了三个判断条件。只要满足其中任意一个条件,都可以提前终止更深的 CU 划分。
方法1:运动一致性检测
该方法是利用空间上相关的 CU(上文提到的L, U, L-U 三个 CU)来判断当前的 CU 是否与周围 CU 属于一致性运动。如果是,则执行 ET 操作。
该算法根据运动矢量(Motion Vector MV)来判断运动一致性,需要用到与当前 CU 深度相同的周围块的运动矢量。如下示意图(蓝色线条表示 LCU 的边界,C 表示当前 CU,红色线条框起来的区域内的 MV 会被用来评估运动一致性,其中的 16x16 或 8x8 表示当前 LCU 在红色区域内的 CU 的大小):
评估运动一致性的方法如下:首先获得红色区域内的所有 4x4 块的 MV,通过下面两个公式计算 MVHx 和 MVHy。计算公式如下:
M V H x = 1 m ∑ ( i , j ) ∈ O ∣ m v x ( i , j ) − 1 m ∑ ( i , j ) ∈ O m v x i , j ∣ {MVH}_{x}=\frac{1}{m}\sum_{(i,j)\in O}|mvx_{(i,j)}-\frac{1}{m}\sum_{(i,j)\in O}mvx_{i,j}| MVHx=m1(i,j)∈O∑∣mvx(i,j)−m1(i,j)∈O∑mvxi,j∣
M V H y = 1 m ∑ ( i , j ) ∈ O ∣ m v y ( i , j ) − 1 m ∑ ( i , j ) ∈ O m v y i , j ∣ {MVH}_{y}=\frac{1}{m}\sum_{(i,j)\in O}|mvy_{(i,j)}-\frac{1}{m}\sum_{(i,j)\in O}mvy_{i,j}| MVHy=m1(i,j)∈O∑∣mvy(i,j)−m1(i,j)∈O∑mvyi,j∣
其中 O O O 表示红色区域内, m m m 表示块的数量, m v x mvx mvx 表示 MV 的 x 分量, m v y mvy mvy 同理。得到 M V H MVH MVH 后,若 M V H x MVH_x MVHx、 M V H y MVH_y MVHy 均小于 0.1,则认为这片区域具有运动一致性,执行 ET 操作。
方法2:RDCost 相似性检测
该方法是基于一个已有研究提出的。该研究认为相关 CU 的 RDCost 通常具有相似的分布。因此如果当前得到的 RDCost 小于一个与周围 CU 的RdCost 相关的阈值,则可以认为当前的划分深度有很大概率是最优的,从而执行 ET 操作。该阈值计算公式如下:
T h r = β ⋅ ∑ i = 0 N − 1 ω i ⋅ R D c o s t i Thr=\beta \cdot\sum_{i=0}^{N-1}\omega_i\cdot RDcost_i Thr=β⋅i=0∑N−1ωi⋅RDcosti
其中 N 是相关 CU 的数量,恒等于 4; R D C o s t i RDCost_i RDCosti 表示第 i 个相关 CU 的RDCost 的值; ω i \omega_i ωi 表示权重:对于 L、Col、U 三个相关 CU,其权重取 0.3;对于 L-U, 其权重取 0.1; β \beta β 为一个阈值,设置为 0.5。
方法3:SKIP 模式检测
该方法比较简单:如果当前 CU 的最优模式是 SKIP 且它的父 CU 的最优模式也是 SKIP,则进行 ET 操作。
HM 编码器修改
我使用的 HM 版本是 16.22。本次复现修改了 TEncCU.cpp、TComDataCU.h、TComPic.h 中的代码。下面将分别说明对数据结构和算法逻辑的修改。
注:以下代码会出现两个自定义的宏:
- PAPER_INTER_SHENLIQUAN:代表 ACUDR 算法
- PAPER_INTER_SHENLIQUAN_2:代表ET算法
数据结构的修改
- 在 TComDataCU.h 中的 TComDataCU 类的声明中加入以下语句:
#if PAPER_INTER_SHENLIQUAN
public:
Int uiBestDepth; //当前 LCU 的最优深度(只有 LCU 有)
Int iInterDepthMin; //当前 LCU 的最小搜索深度
Int iInterDepthMax; //当前 LCU 的最大搜索深度
Bool bInterEarlyStopFlag; // 标志位,代表当前 LCU 是否适用 ACUDR 算法
#endif
#if PAPER_INTER_SHENLIQUAN_2
public:
TComDataCU *parentCU; //当前 CU 的父 CU
#endif
其中的 bInterEarlyStopFlag 表示是否适用当前的算法。在执行的过程中,只有其为 true 时才会进行 ACUDR 算法,否则按照常规步骤进行。不适用的情况包括但不限于:当前帧为 I 帧、当前 LCU 的相邻 LCU 不存在等。
- TComPic.h 中,在 TComPic 类的声明中加入以下代码:
//public
#if PAPER_INTER_SHENLIQUAN
UInt auiBestDepthInCtu[2048]; //用于保存 LCU 的最优深度
#endif
#if PAPER_INTER_SHENLIQUAN_2
Double audRDCostInCtu[2048]; //用于保存 LCU 的 RDCost
#endif
由于一帧图像编码完成后,其对应的编码单元都会被释放,使得在后续的编码中无法得到 Col-CU。为了方便起见,我将后续编码会使用到的信息保存在 Pic 中,之后便可以通过参考 Pic 获得对应的信息。
这些信息以 LCU 为单位保存,偏移量设置为 2048 可以保证最高在编码 8K 的视频时不会发生溢出。
对于这些信息的更新放在 TEncSlice.cpp 文件中,在 compressSlice 函数中调用完 compressCtu 后将处理完的 CTU 信息写入 Pic 中。(注:在 HM 中,Ctu 通常指的就是 LCU)。这部分的代码如下:
#if PAPER_INTER_SHENLIQUAN
pCtu->bInterEarlyStopFlag = false; //初始化标志
#endif
m_pcCuEncoder->compressCtu( pCtu );//处理 CTU,源码中已有的代码
#if PAPER_INTER_SHENLIQUAN
//将当前 LCU 最优深度写入 Pic
pcPic->auiBestDepthInCtu[ctuRsAddr] = pCtu->uiBestDepth;
#endif
#if PAPER_INTER_SHENLIQUAN_2
//将当前 LCU 的 RdCost 写入 Pic
pcPic->audRDCostInCtu[ctuRsAddr] = pCtu->getTotalCost();
#endif
算法的修改
算法部分在 TEncCu.cpp 中的 xCompress 函数中实现。这个函数是比较重要的一个函数,可以参考这篇博客中关于 xCompress 函数的讲解。
- 声明我们要使用到的变量,这个放在函数的最前面。代码如下:
#if (PAPER_INTER_SHENLIQUAN_2) || (PAPER_INTER_SHENLIQUAN)
TComDataCU *pcLCU = pcPic->getCtu(rpcTempCU->getCtuRsAddr()); //当前的 LCU
TComDataCU *aboveLCU = pcLCU->getCtuAbove(); //上方的 LCU
TComDataCU *leftLCU = pcLCU->getCtuLeft(); //左侧的 LCU
TComDataCU *aboveleftLCU = pcLCU->getCtuAboveLeft(); //左上的 LCU
TComPic * pcColPic = pcLCU->getSlice()->getRefPic(RefPicList(pcLCU->getSlice()->isInterB() ? 1-pcLCU->getSlice()->getColFromL0Flag() : 0),
pcLCU->getSlice()->getColRefIdx());
//参考图片
#endif
#if PAPER_INTER_SHENLIQUAN_2
Bool ETFlag = false;
#endif
- 紧接着开始 ACUDR 算法,根据周围 LCU 的信息确定搜索深度范围。代码如下:
#if PAPER_INTER_SHENLIQUAN
Bool bInterEarlyStopFlag = false;
//如果参考图片不存在,则 ColBestDepth = -1
Int ColBestDepth = pcColPic?pcColPic->auiBestDepthInCtu[rpcTempCU->getCtuRsAddr()]:-1;
//判断是否适用 ACUDR
if(rpcTempCU->getSlice()->getSliceType()!=I_SLICE && uiDepth== 0 && aboveLCU && leftLCU && aboveleftLCU && ColBestDepth != -1){
bInterEarlyStopFlag = true;
}
//如果适用,则计算 Depth_pred 并更新 pcLCU 的搜索深度范围
if(bInterEarlyStopFlag){
pcLCU->bInterEarlyStopFlag = true;
Double value = 0.3*double(aboveLCU->uiBestDepth)+0.3*double(leftLCU->uiBestDepth)+0.3*double(ColBestDepth)+0.1*double(aboveleftLCU->uiBestDepth);
if(value==0){
pcLCU->iInterDepthMax = 0;
pcLCU->iInterDepthMin = 0;
}
else if(value<=0.5){
pcLCU->iInterDepthMax = 1;
pcLCU->iInterDepthMin = 0;
}
else if(value<1.5){
pcLCU->iInterDepthMax = 2;
pcLCU->iInterDepthMin = 0;
}
else if(value<2.5){
pcLCU->iInterDepthMax = 3;
pcLCU->iInterDepthMin = 1;
}
else{
pcLCU->iInterDepthMax = 3;
pcLCU->iInterDepthMin = 2;
}
}
#endif
- 由于 xCompressCU 先检测当前深度 CU 的最优模式,之后在进行划分检测,因此在进行检测前需要判断当前的深度是否大于等于最小搜索深度。若是,则进行检测。在进入 QP 的 for 循环前加入以下判断:
#if PAPER_INTER_SHENLIQUAN
//判断是否满足条件
if(!pcLCU->bInterEarlyStopFlag || uiDepth>=pcLCU->iInterDepthMin)
#endif
//编码器原本就有的代码
for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++){...}
一共有两个地方:一个是 !bBoundary 下面,一个是 !earlyDetectionSkipMode 下面。
如果不进行当前深度的检测,那么当前深度的最优 RDCost 就会是 MAX_DOUBLE。也就是说在后面只要进行了下一深度的检测,最后一定不会选择到当前深度的 CU,因此不用考虑其它的问题。
- 在当前深度的 RDCost 测试完后,在进行分割测试之前可以开展 ET 检测和 ACUDR 的最大深度检测。如果满足 ET 条件,或者是当前深度等于 LCU 的最大深度范围,都可以不进行下一步的划分。这一部分的代码如下:
//这句代码是源码中就有的,用于标识新代码的位置
const Bool bSubBranch = bBoundary || !( m_pcEncCfg->getUseEarlyCU() && rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isSkipped(0) );
#if PAPER_INTER_SHENLIQUAN
//如果使用了 ACUDR 算法,则判断通过该算法是否已经能够提前终止划分了
//如果是,则没有必要再进行 ET 算法了
Bool earlyStop = false;
if(pcLCU->bInterEarlyStopFlag && uiDepth>=pcLCU->iInterDepthMax &&!bBoundary){
earlyStop = true;
}
#endif
#if PAPER_INTER_SHENLIQUAN_2
//当前 CU 不为边界 CU, 为 LCU 左上角,深度小于3,为PB帧,且邻居 LCU 存在时,使用该方法
//uiDepth>=pcLCU->iInterDepthMin 单独解释
if(!bBoundary &&
#if PAPER_INTER_SHENLIQUAN
!earlyStop && uiDepth>=pcLCU->iInterDepthMin &&
#endif
uiDepth<3 && rpcBestCU->getZorderIdxInCtu() == 0
&& pcLCU->getSlice()->getSliceType() != I_SLICE
&& aboveLCU && leftLCU && aboveleftLCU){
//method 1,计算运动一致性
Int mv_count = 0;
std::vector<TComMv> allMv;
Int leftMinIdx = 1;
Int leftMaxIdx = -1;
Int aboveMinIdx = 1;
Int aboveMaxIdx = -1;
Int aboveleftMinIdx = 1;
Int aboveleftMaxIdx = -1;
//得到各相邻 CU 需要遍历的 4x4 小 CU 的范围
if(uiDepth == 0){
leftMinIdx = 0;
leftMaxIdx = 255;
aboveMinIdx = 0;
aboveMaxIdx = 255;
aboveleftMinIdx = 0;
aboveleftMaxIdx = 255;
}
else if(uiDepth == 1){
leftMinIdx = 64;
leftMaxIdx = 127;
aboveMinIdx = 128;
aboveMaxIdx =191;
aboveleftMinIdx = 192;
aboveleftMaxIdx = 255;
}
else if(uiDepth == 2){
leftMinIdx = 80;
leftMaxIdx = 95;
aboveMinIdx = 160;
aboveMaxIdx = 175;
aboveleftMinIdx = 240;
aboveleftMaxIdx = 255;
}
else{
//如果当前深度为 3 ,说明已经达到最大深度,不会再继续划分。因此无需处理
}
//LeftCU
for(Int idx=leftMinIdx;idx<=leftMaxIdx;){
TComMv mv = leftLCU->getCUMvField(REF_PIC_LIST_0)->getMv(idx);
Int step = 1 << (2*(4-leftLCU->getDepth(idx)));
mv = TComMv(step*mv.getHor(),step*mv.getVer());
mv_count += step;
allMv.push_back(mv);
idx += step;
}
//AboveCU
for(Int idx=aboveMinIdx;idx<=aboveMaxIdx;){
TComMv mv = aboveLCU->getCUMvField(REF_PIC_LIST_0)->getMv(idx);
Int step = 1 << (2*(4-aboveLCU->getDepth(idx)));
mv = TComMv(step*mv.getHor(),step*mv.getVer());
mv_count += step;
allMv.push_back(mv);
idx += step;
}
//AboveleftCU
for(Int idx=aboveleftMinIdx;idx<aboveleftMaxIdx;){
TComMv mv = aboveleftLCU->getCUMvField(REF_PIC_LIST_0)->getMv(idx);
Int step = 1 <<(2*(4-aboveleftLCU->getDepth(idx)));
mv = TComMv(step*mv.getHor(),step*mv.getVer());
mv_count += step;
allMv.push_back(mv);
idx += step;
}
//CurrentCU
Int currentMaxIdx = 1 << (2*(4-uiDepth));
for(Int idx=0;idx<currentMaxIdx;idx++){
TComMv mv = rpcBestCU->getCUMvField(REF_PIC_LIST_0)->getMv(idx);
allMv.push_back(mv);
mv_count++;
}
//计算运动相似度
Int Hor_sum = 0;
Int Ver_sum = 0;
Double Hor_mean = 0;
Double Ver_mean = 0;
for(Int i=0;i<allMv.size();i++){
Hor_sum += allMv[i].getHor();
Ver_sum += allMv[i].getVer();
}
Hor_mean = (double)Hor_sum/(double)mv_count;
Ver_mean = (double)Ver_sum/(double)mv_count;
// std::cout<<Hor_mean<<" "<<Ver_mean<<std::endl;
Double Hor_diff = 0.0;
Double Ver_diff = 0.0;
for(Int i=0;i<allMv.size();i++){
Hor_diff += std::abs((double)allMv[i].getHor()-Hor_mean);
Ver_diff += std::abs((double)allMv[i].getVer()-Ver_mean);
}
Hor_diff /= (double)mv_count;
Ver_diff /= (double)mv_count;
if(Hor_diff < 0.1 && Ver_diff < 0.1){
ETFlag = true;
}
//end of Method1
//method2
if(!ETFlag){
Double colRdCost = pcColPic->audRDCostInCtu[rpcTempCU->getCtuRsAddr()]/std::pow(4,uiDepth);
Double aboveRdCost = aboveLCU->getTotalCost()/std::pow(4,uiDepth);
Double leftRdCost = leftLCU->getTotalCost()/std::pow(4,uiDepth);
Double aboveleftRdCost = aboveleftLCU->getTotalCost()/std::pow(4,uiDepth);
Double currentCost = rpcBestCU->getTotalCost();
if(currentCost<0.5*(0.3*colRdCost+0.3*aboveRdCost+0.3*leftRdCost+0.1*aboveleftRdCost)){
ETFlag = true;
}
}
//method3
if(!ETFlag){
if(uiDepth>=1){
if(rpcBestCU->parentCU->getSkipFlag(0) && rpcBestCU->getSkipFlag(0)){
ETFlag = true;
}
}
}
}
#endif
其中,uiDepth>=pcLCU->iInterDepthMin 用来判断当前深度是否进行了检测。显然,如果当前深度没有进行检测,并且 ET 算法又跳过了更大深度的 CU,相当于当前 CU 没有进行编码,这显然是不行的。因此,如果当前深度没有检测的话,则一定需要划分,因此不进行 ET 检测。
之后利用 earlyStop 和 ETFlag 两个参数判断是否进一步划分。如果两个 flag 均为 false,则需要进一步划分。代码如下:
if(
#if PAPER_INTER_SHENLIQUAN
!earlyStop &&
#endif
#if PAPER_INTER_SHENLIQUAN_2
!ETFlag &&
#endif
bSubBranch && uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() && (!getFastDeltaQp() || uiWidth > fastDeltaQPCuMaxSize || bBoundary))
{
//further split
}
之后在 TypeDef.h 中将两个宏定义为 1,编译即可。
本地实验结果
我跑了几个测试序列,QP 取 22 27 32 37 四个值,分别对源编码器、只使用 ACUDR 算法、只使用 ET 算法、两个算法同时使用四种模式进行编码性能测试,数据如下:
视频序列 | 使用的算法 | QP22 | QP27 | QP32 | QP37 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
耗时(s) | 比特率(kbps) | PSNR(dB) | 耗时(s) | 比特率(kbps) | PSNR(dB) | 耗时(s) | 比特率(kbps) | PSNR(dB) | 耗时(s) | 比特率(kbps) | PSNR(dB) | ||
PeoPleOnStreet(2560x1600) | 源编码器 | 2135.351 | 43969.848 | 41.7587 | 1687.424 | 21190.632 | 38.8409 | 1431.218 | 11233.848 | 36.0748 | 1270.983 | 6353.04 | 33.4698 |
ADRD | 1336.967 | 44076.288 | 41.7489 | 1008.498 | 21321.264 | 38.8236 | 848.179 | 11400.552 | 36.0491 | 754.065 | 6535.848 | 33.4203 | |
ET | 2095.39 | 44017.128 | 41.7567 | 1641.838 | 21230.16 | 38.8404 | 1366.855 | 11236.512 | 36.0688 | 1178.88 | 6360.672 | 33.4642 | |
Overall | 1332.21 | 44092.992 | 41.7495 | 1002.343 | 21368.664 | 38.8291 | 839.468 | 11396.76 | 36.0473 | 747.321 | 6534.696 | 33.416 | |
BasketballDrive(1920x1088) | 源编码器 | 908.835 | 17665.92 | 41.1338 | 716.316 | 6457.44 | 39.7688 | 614.884 | 3191.16 | 38.226 | 551.802 | 1751.64 | 36.438 |
ADRD | 586.607 | 18170.72 | 41.1035 | 458.72 | 6739.48 | 39.6682 | 400.23 | 3420.68 | 37.9914 | 366.388 | 1953.36 | 36.0415 | |
ET | 812.217 | 17753.96 | 41.1171 | 639.529 | 6552.72 | 39.7528 | 536.879 | 3269.08 | 38.2201 | 471.813 | 1778.2 | 36.4197 | |
Overall | 580.507 | 18169.96 | 41.1019 | 458.705 | 6731.44 | 39.6676 | 393.329 | 3431.2 | 38.0041 | 358.632 | 1960.12 | 36.0328 | |
Tennis(1920x1088) | 源编码器 | 981.261 | 8533.402 | 42.0856 | 805.146 | 4141.459 | 40.3336 | 702.589 | 2115.091 | 38.2698 | 625.548 | 1124.333 | 36.1714 |
ADRD | 619.037 | 8743.93 | 42.0591 | 518.187 | 4281.254 | 40.2459 | 445.334 | 2240.026 | 38.101 | 385.764 | 1247.078 | 35.8406 | |
ET | 921.406 | 8639.539 | 42.078 | 753.155 | 4178.074 | 40.3222 | 618.57 | 2144.986 | 38.2579 | 528.426 | 1142.285 | 36.1237 | |
Overall | 614.314 | 8736.346 | 42.0556 | 496.91 | 4282.656 | 40.2404 | 427.608 | 2235.859 | 38.1007 | 379.888 | 1246.579 | 35.8241 | |
BasketBallDrill(832x480) | 源编码器 | 251.077 | 4683.96 | 41.5045 | 192.635 | 2315.12 | 38.4939 | 177.234 | 1163.52 | 35.7253 | 167.045 | 622.64 | 33.3902 |
ADRD | 168.495 | 4739.16 | 41.464 | 134.508 | 2346 | 38.428 | 109.229 | 1197.88 | 35.6638 | 106.762 | 661.2 | 33.2916 | |
ET | 218.388 | 4714.88 | 41.5038 | 173.663 | 2322.64 | 38.4996 | 146.492 | 1166.12 | 35.7314 | 120.898 | 621.8 | 33.3793 | |
Overall | 120.637 | 4747.16 | 41.6948 | 96.576 | 2344.12 | 38.6391 | 80.773 | 1197.88 | 35.8873 | 72.753 | 659.48 | 33.5085 | |
RaceHorses(832x480) | 源编码器 | 273.384 | 7389.84 | 40.0083 | 208.706 | 3416.112 | 36.751 | 168.977 | 1686.576 | 33.8526 | 143.467 | 839.04 | 31.1826 |
ADRD | 188.454 | 7435.008 | 40.0186 | 138.095 | 3433.44 | 36.7304 | 110.771 | 1713.36 | 33.8387 | 93.656 | 865.056 | 31.1184 | |
ET | 261.1 | 7414.872 | 40.0039 | 196.882 | 3424.584 | 36.7406 | 158.510 | 1690.56 | 33.8524 | 131.139 | 841.176 | 31.1813 | |
Overall | 187.47 | 7429.704 | 40.0112 | 135.974 | 3433.368 | 36.724 | 109.292 | 1709.904 | 33.8186 | 92.549 | 862.68 | 31.1269 | |
BasketBallPass(416x240) | 源编码器 | 34.937 | 1212.72 | 42.362 | 30.165 | 650.96 | 38.9984 | 26.034 | 343 | 35.9032 | 23.599 | 181.24 | 33.1319 |
ADRD | 26.969 | 1217.36 | 42.3562 | 23.307 | 654.04 | 38.9788 | 20.190 | 348.32 | 35.864 | 18.787 | 189.6 | 33.0968 | |
ET | 31.492 | 1238.92 | 42.3445 | 26.987 | 657.08 | 38.9903 | 22.858 | 349.04 | 35.8836 | 20.245 | 182.44 | 33.1312 | |
Overall | 26.934 | 1217.36 | 42.3562 | 22.946 | 654.04 | 38.9784 | 19.842 | 348.32 | 35.8642 | 18.682 | 189.64 | 33.0968 | |
RaceHorses(416x240) | 源编码器 | 64.771 | 1902.264 | 40.3985 | 52.575 | 1008.024 | 36.6775 | 43.179 | 528.024 | 33.3665 | 36.258 | 275.16 | 30.6126 |
ADRD | 50.725 | 1906.008 | 40.3994 | 40.585 | 1008.408 | 36.6721 | 32.409 | 532.944 | 33.3519 | 27.092 | 277.896 | 30.5414 | |
ET | 64.618 | 1904.208 | 40.4069 | 51.8 | 1007.88 | 36.6752 | 42.210 | 527.736 | 33.3566 | 35.203 | 274.008 | 30.5776 | |
Overall | 51.272 | 1904.328 | 40.3974 | 40.53 | 1012.368 | 36.6776 | 32.392 | 532.944 | 33.3519 | 27.092 | 279.456 | 30.5576 | |
KristenAndSara(1280x720) | 源编码器 | 261.007 | 3962.832 | 44.3981 | 223.252 | 1913.28 | 42.5937 | 205.34 | 1051.392 | 40.3836 | 196.786 | 614.832 | 37.9179 |
ADRD | 174.386 | 4065.504 | 44.3857 | 156.343 | 1995.168 | 42.5592 | 146.252 | 1113.072 | 40.3143 | 139.347 | 657.216 | 37.8022 | |
ET | 212.808 | 3965.008 | 44.3769 | 164.463 | 1936.992 | 42.5794 | 138.224 | 1061.568 | 40.3822 | 117.919 | 618.576 | 37.9045 | |
Overall | 170.902 | 4064.064 | 44.387 | 149.726 | 1997.088 | 42.5656 | 139.056 | 1114.704 | 40.3 | 132.739 | 653.808 | 37.784 | |
SlideShow(1280x720) | 源编码器 | 311.02 | 1466.464 | 51.1738 | 293.753 | 951.216 | 48.0506 | 278.993 | 661.904 | 45.1391 | 260.574 | 490.864 | 41.942 |
ADRD | 214.719 | 1558.64 | 50.9355 | 200.168 | 1022.688 | 47.6767 | 191.54 | 732.64 | 44.4725 | 185.674 | 548.24 | 41.4421 | |
ET | 142.849 | 1692.336 | 50.8845 | 128.317 | 1087.488 | 47.5639 | 116.821 | 748.016 | 44.5486 | 117.227 | 528.432 | 41.2836 | |
Overall | 206.216 | 1563.536 | 50.8881 | 194.412 | 1025.808 | 47.6063 | 183.759 | 741.44 | 44.3177 | 177.327 | 547.84 | 41.2388 | |
FourPeople(1280x720) | 源编码器 | 245.279 | 4815.264 | 43.798 | 209.652 | 2457.408 | 41.773 | 197.398 | 1443.024 | 39.3763 | 190.529 | 863.424 | 36.6326 |
ADRD | 167.413 | 4854.096 | 43.7862 | 147.688 | 2501.04 | 41.7585 | 139.624 | 1488.624 | 39.3557 | 137.554 | 903.072 | 36.5938 | |
ET | 167.983 | 4788.192 | 43.7617 | 128.986 | 2459.184 | 41.7627 | 105.406 | 1446.048 | 39.3671 | 94.543 | 868.512 | 36.6275 | |
Overall | 163.24 | 4860.48 | 43.7882 | 137.923 | 2510.88 | 41.7617 | 128.434 | 1487.856 | 39.3524 | 124.892 | 903.696 | 36.5936 |
与源编码器的性能比较:
视频序列 | 使用的算法 | QP22 | QP27 | QP32 | QP37 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DT(%) | BDBR(%) | BDPSNR(dB) | DT(%) | BDBR(%) | BDPSNR(dB) | DT(%) | BDBR(%) | BDPSNR(dB) | DT(%) | BDBR(%) | BDPSNR(dB) | ||
PeoPleOnStreet(2560x1600) | 源编码器 | ||||||||||||
ADRD | 37.39% | 0.24% | -0.0098 | 40.23% | 0.62% | -0.0173 | 40.74% | 1.48% | -0.0257 | 40.67% | 2.88% | -0.0495 | |
ET | 1.87% | 0.11% | -0.002 | 2.70% | 0.19% | -0.0005 | 4.50% | 0.02% | -0.006 | 7.25% | 0.12% | -0.0056 | |
Overall | 37.61% | 0.28% | -0.0092 | 40.60% | 0.84% | -0.0118 | 41.35% | 1.45% | -0.0275 | 41.20% | 2.86% | -0.0538 | |
BasketballDrive(1920x1088) | 源编码器 | ||||||||||||
ADRD | 35.46% | 2.86% | -0.0303 | 35.96% | 4.37% | -0.1006 | 34.91% | 7.19% | -0.2346 | 33.60% | 11.52% | -0.3965 | |
ET | 10.63% | 0.50% | -0.0167 | 10.72% | 1.48% | -0.016 | 12.69% | 2.44% | -0.0059 | 14.50% | 1.52% | -0.0183 | |
Overall | 36.13% | 2.85% | -0.0319 | 35.96% | 4.24% | -0.1012 | 36.03% | 7.52% | -0.2219 | 35.01% | 11.90% | -0.4052 | |
Tennis(1920x1088) | 源编码器 | ||||||||||||
ADRD | 36.91% | 2.47% | -0.0265 | 35.64% | 3.38% | -0.0877 | 36.62% | 5.91% | -0.1688 | 38.33% | 10.92% | -0.3308 | |
ET | 6.10% | 1.24% | -0.0076 | 6.46% | 0.88% | -0.0114 | 11.96% | 1.41% | -0.0119 | 15.53% | 1.60% | -0.0477 | |
Overall | 37.40% | 2.38% | -0.03 | 38.28% | 3.41% | -0.0932 | 39.14% | 5.71% | -0.1691 | 39.27% | 10.87% | -0.3473 | |
BasketBallDrill(832x480) | 源编码器 | ||||||||||||
ADRD | 32.89% | 1.18% | -0.0405 | 30.17% | 1.33% | -0.0659 | 38.37% | 2.95% | -0.0615 | 36.09% | 6.19% | -0.0986 | |
ET | 13.02% | 0.66% | -0.0007 | 9.85% | 0.32% | 0.0057 | 17.35% | 0.22% | 0.0061 | 27.63% | -0.13% | -0.0109 | |
Overall | 51.95% | 1.35% | 0.1903 | 49.87% | 1.25% | 0.1452 | 54.43% | 2.95% | 0.162 | 56.45% | 5.92% | 0.1183 | |
RaceHorses(832x480) | 源编码器 | ||||||||||||
ADRD | 31.07% | 0.61% | 0.0103 | 33.83% | 0.51% | -0.0206 | 34.45% | 1.59% | -0.0139 | 34.72% | 3.10% | -0.0642 | |
ET | 4.49% | 0.34% | -0.0044 | 5.67% | 0.25% | -0.0104 | 6.19% | 0.24% | -0.0002 | 8.59% | 0.25% | -0.0013 | |
Overall | 31.43% | 0.54% | 0.0029 | 34.85% | 0.51% | -0.027 | 35.32% | 1.38% | -0.034 | 35.49% | 2.82% | -0.0557 | |
BasketBallPass(416x240) | 源编码器 | ||||||||||||
ADRD | 22.81% | 0.38% | -0.0058 | 22.73% | 0.47% | -0.0196 | 22.45% | 1.55% | -0.0392 | 20.39% | 4.61% | -0.0351 | |
ET | 9.86% | 2.16% | -0.0175 | 10.54% | 0.94% | -0.0081 | 12.20% | 1.76% | -0.0196 | 14.21% | 0.66% | -0.0007 | |
Overall | 22.91% | 0.38% | -0.0058 | 23.93% | 0.47% | -0.02 | 23.78% | 1.55% | -0.039 | 20.84% | 4.63% | -0.0351 | |
RaceHorses(416x240) | 源编码器 | ||||||||||||
ADRD | 21.69% | 0.20% | 0.0009 | 22.81% | 0.04% | -0.0054 | 24.94% | 0.93% | -0.0146 | 25.28% | 0.99% | -0.0712 | |
ET | 0.24% | 0.10% | 0.0084 | 1.47% | -0.01% | -0.0023 | 2.24% | -0.05% | -0.0099 | 2.91% | -0.42% | -0.035 | |
Overall | 20.84% | 0.11% | -0.0011 | 22.91% | 0.43% | 1E-04 | 24.98% | 0.93% | -0.0146 | 25.28% | 1.56% | -0.055 | |
KristenAndSara(1280x720) | 源编码器 | ||||||||||||
ADRD | 33.19% | 2.59% | -0.0124 | 29.97% | 4.28% | -0.0345 | 28.78% | 5.87% | -0.0693 | 29.19% | 6.89% | -0.1157 | |
ET | 18.47% | 0.05% | -0.0212 | 26.33% | 1.24% | -0.0143 | 32.69% | 0.97% | -0.0014 | 40.08% | 0.61% | -0.0134 | |
Overall | 34.52% | 2.55% | -0.0111 | 32.93% | 4.38% | -0.0281 | 32.28% | 6.02% | -0.0836 | 32.55% | 6.34% | -0.1339 | |
SlideShow(1280x720) | 源编码器 | ||||||||||||
ADRD | 30.96% | 6.29% | -0.2383 | 31.86% | 7.51% | -0.3739 | 31.35% | 10.69% | -0.6666 | 28.74% | 11.69% | -0.4999 | |
ET | 54.07% | 15.40% | -0.2893 | 56.32% | 14.33% | -0.4867 | 58.13% | 13.01% | -0.5905 | 55.01% | 7.65% | -0.6584 | |
Overall | 33.70% | 6.62% | -0.2857 | 33.82% | 7.84% | -0.4443 | 34.13% | 12.02% | -0.8214 | 31.95% | 11.61% | -0.7032 | |
FourPeople(1280x720) | 源编码器 | ||||||||||||
ADRD | 31.75% | 0.81% | -0.0118 | 29.56% | 1.78% | -0.0145 | 29.27% | 3.16% | -0.0206 | 27.80% | 4.59% | -0.0388 | |
ET | 31.51% | -0.56% | -0.0363 | 38.48% | 0.07% | -0.0103 | 46.60% | 0.21% | -0.0092 | 50.38% | 0.59% | -0.0051 | |
Overall | 33.45% | 0.94% | -0.0098 | 34.21% | 2.18% | -0.0113 | 34.94% | 3.11% | -0.0239 | 34.45% | 4.66% | -0.039 |
跟文献中的数据对比,发现大多数情况下的编码时间减少的并没有那么多。经分析可能有以下几个原因:
- 由于时间和电脑的算力原因,我在编码时只编了前10帧,数据具有偶然性(因为有些序列提速的幅度也比文献中的结果来得大,例如SlideShow 和 FourPeople 在只使用 ET 的时候。而且前者比特率还炸了…)
- 文献中使用的参考帧结构是 Hierarchical B-picture,而我使用的结构是 HM 软件手册中的结构。这两种结构在相同的 GOPSize 下 B 帧的数量不同,前者会比后者来得多,因此使用后者在性能的提升上会比前者来得少。(主要是我还不太会在 HM 中指定参考帧结构,只会用默认的,TwT)
总结
这应该算是我第一篇完整复现并且进行过大量测试的文献了,也是我这段时间的一个工作成果。虽然一开始毫无头绪,盯着源码看了半天,还写了不少 bug。但在最后得到结果的时候,还是挺开心的(O(∩_∩)O~~)。