H.266/VVC SCC技术学习:块差分脉冲编码调整(block differential pulse coded modulation, BDPCM)
近年来,屏幕内容视频广泛用于多媒体应用,例如远程桌面,屏幕共享等。由于屏幕内容视频的特性与自然视频有较大区别,VVC中使用了帧内块复制(intra block copy, 即IBC), 调色板(Palette), 变换跳过(transform skip, 即TS), 块差分脉冲编码调制(block differential pulse coded modulation ,即BDPCM)等技术来提高其编码效率。本文将阐述BDPCM技术的实现原理。
一、BDPCM技术简介
在VVC中,BDPCM在提案 JVET-M0057 中被提出。
在SPS层需要传输 BDPCM 启用标志,仅当SPS层传输了 Transform Skip 标志才会传输该标志。
在 CU 层,如果 CU 允许使用 Transform Skip 技术时(像素数 <= MaxTsSize×MaxTsSize)才允许使用 BDPCM 技术。如果 CU 使用帧内编码时,需要进一步传输 CU 级标志表明当前 CU 采用帧内编码还是 BDPCM 编码,如果采用 BDPCM 编码,则进一步需要传输一个 BDPCM 预测方向标志位标识当前 CU 采用水平预测方向还是垂直预测方向。
void CABACWriter::bdpcm_mode( const CodingUnit& cu, const ComponentID compID )
{
if( !cu.cs->sps->BDPCM) return;
if( !CU::bdpcmAllowed( cu, compID ) ) return;
int bdpcmMode = cu.bdpcmM[toChannelType(compID)];
unsigned ctxId = isLuma(compID) ? 0 : 2;
// BDPCM 启用标志位
m_BinEncoder.encodeBin(bdpcmMode > 0 ? 1 : 0, Ctx::BDPCMMode(ctxId));
if (bdpcmMode)
{
// BDPCM 预测方向标志位
m_BinEncoder.encodeBin(bdpcmMode > 1 ? 1 : 0, Ctx::BDPCMMode(ctxId+1));
}
}
对于 BDPCM 编码的 CU,通过以下四步进行预测过程:
1)编码器使用未滤波的参考像素,通过BDPCM所选择的预测方向对编码单元做普通的帧内预测(水平或者垂直);
void IntraPrediction::xPredIntraBDPCM(PelBuf& pDst, const CPelBuf& pSrc, const uint32_t dirMode, const ClpRng& clpRng)
{
const int wdt = pDst.width;
const int hgt = pDst.height;
const int strideP = pDst.stride;
const int strideS = pSrc.stride;
CHECK(!(dirMode == 1 || dirMode == 2), "Incorrect BDPCM mode parameter.");
Pel* pred = &pDst.buf[0];
if (dirMode == 1)
{
Pel val;
for (int y = 0; y < hgt; y++)
{
val = pSrc.buf[(y + 1) + strideS];
for (int x = 0; x < wdt; x++)
{
pred[x] = val;
}
pred += strideP;
}
}
else
{
for (int y = 0; y < hgt; y++)
{
for (int x = 0; x < wdt; x++)
{
pred[x] = pSrc.buf[x + 1];
}
pred += strideP;
}
}
}
2)普通帧内预测得到的残差被直接量化;
3)编码器沿着BDPCM所选择的方向对量化后的残差做进一步预测。BDPCM将每个位置的量化残差与该方向的上一个相邻量化残差计算得到差值。最后,编码器将这些差值编码并且传输到解码端。计算差值的具体过程如下所示:
对于一个大小为 M× N的块,设(其中
,
)为预测残差。设
表示残差
的量化后的结果。BDPCM 应用于量化后的残差值,得到一个修改后的
数组
,其元素为
,这里
是从其相邻的量化残差值预测得到的。
对于垂直BDPCM技术,通常通过以下计算得到
对于水平BDPCM技术,通常通过以下计算得到
void fwdResDPCM( TransformUnit& tu, const ComponentID compID )
{
const CompArea& rect = tu.blocks[compID];
const int wdt = rect.width;
const int hgt = rect.height;
CoeffSigBuf coeffs = tu.getCoeffs(compID);
TCoeffSig* coef = &coeffs.buf[0];
if (tu.cu->bdpcmM[toChannelType(compID)] == 1)
{
for( int y = 0; y < hgt; y++ )
{
for( int x = wdt - 1; x > 0; x-- )
{
coef[x] -= coef[x - 1];
}
coef += coeffs.stride;
}
}
else
{
coef += coeffs.stride * (hgt - 1);
for( int y = 0; y < hgt - 1; y++ )
{
for ( int x = 0; x < wdt; x++ )
{
coef[x] -= coef[x - coeffs.stride];
}
coef -= coeffs.stride;
}
}
}
对于解码端,量化后的残差 可以通过此预测过程的逆过程得到
将反量化后的残差与帧内块预测值相加,得到重建像素。
Deblock过程中,如果块边界两侧的两个块都使用 BDPCM 进行编码,那么该特定的块边界将不进行滤波处理。
二、编码增益
在VVC参考软件VTM-10.0中,关闭BDPCM对ClassF和ClassTGM的标准测试序列有如下影响:
Acronym | BDR-Y | BDR-U | BDR-V | Tester EncTime | Tester DecTime | XChecker EncTime | XChecker DecTime |
AI | |||||||
BDPCM ClassF | 0.93% | 0.92% | 0.97% | 98% | 105% | 101% | 105% |
BDPCM ClassTGM | 1.45% | 1.58% | 1.58% | 101% | 103% | 92% | 94% |
RA | |||||||
BDPCM ClassF | 0.70% | 0.68% | 0.93% | 99% | 100% | 100% | 103% |
BDPCM ClassTGM | 0.79% | 1.03% | 0.98% | 100% | 101% | 92% | 84% |
LD | |||||||
BDPCM ClassF | 0.35% | -0.37% | 0.35% | 100% | 103% | 96% | 98% |
BDPCM ClassTGM | 0.29% | 0.42% | 0.37% | 99% | 99% | 95% | 83% |