VVC支持色度联合编码(joint coding of chroma residual ,JCCR)模式。

色度联合编码模式的使用(激活)由TU级标志tu_joint_cbcr_residual_flag表示,所选模式由色度CBFs隐式表示。如果一个TU的色度CBFs中的一个或两个都等于1(tu_cbf_cb或者tu_cbf_cr),则存在标志tu_joint_cbcr_residual_flag

在PPS和slice head中,联合色度残差编码模式下的色度QP偏移值与常规色度残差编码模式下的色度QP偏移值不同,这些色度QP偏移值用于推导使用联合色度残差编码模式编码的块的色度QP值。

JCCR模式有3个子模式。当相应的联合色度编码模式(表中的模式2)在TU中激活时,在对该TU进行量化和解码时,将该色度QP偏移添加到应用的亮度派生色度QP中(the applied luma-derived chroma QP)。对于其他模式(表中的模式1和模式3),色度QPs的推导方法与常规Cb或Cr块相同。

传输变换块的色度残差(resCb和resCr)的重建过程如表所示。当JCCR模式被激活时,一个联合色度残差块(resJointC [x] [y]被传递过来,然后通过考虑各种信息(比如tu_cbf_cb tu_cbf_cr, CSign)推导出残差块Cb (resCb)和残差块Cr (resCr)。

在编码器端,联合色度分量的推导如下。根据模式(如上表所示),编码器产生resJointC{1,2}如下:

若mode = 2(重构后的单个残差Cb = C, Cr = CSign * C),则根据

   -resJointC[ x ][ y ] = ( resCb[ x ][ y ] + CSign * resCr[ x ][ y ] ) / 2.

否则,若mode = 1(重构后的单个残差Cb = C, Cr = (CSign * C) / 2),则根据

 -resJointC[ x ][ y ] = ( 4 * resCb[ x ][ y ] + 2 * CSign * resCr[ x ][ y ] ) / 5.

否则(mode = 3,重构后的单个残差Cr = C, Cb = (CSign * C) / 2),根据

-resJointC[ x ][ y ] = ( 4 * resCr[ x ][ y ] + 2 * CSign * resCb[ x ][ y ] ) / 5.

tu_cbf_cb

tu_cbf_cr

reconstruction of Cb and Cr residuals

mode

1

0

resCb[ x ][ y ] = resJointC[ x ][ y ]
resCr[ x ][ y ] = ( CSign * resJointC[ x ][ y ] ) >> 1

1

1

1

resCb[ x ][ y ] = resJointC[ x ][ y ]
resCr[ x ][ y ] = CSign * resJointC[ x ][ y ]

2

0

1

resCb[ x ][ y ] = ( CSign * resJointC[ x ][ y ] ) >> 1
resCr[ x ][ y ] = resJointC[ x ][ y ]

3

上述三种联合色度编码模式仅在I片上受支持。在P和B片中,只支持模式2。因此,在P和B片中,语法元素tu_joint_cbcr_residual_flag仅在色度cbfs都为1时才存在(即tu_cbf_cb=1且tu_cbf_cr=1)。

JCCR模式可以与色度变换跳过(TransformSkip,TS)模式相结合。 为了加快编码端选择速度,JCCR变换的选择取决于Cb和Cr分量的独立编码是否选择DCT-2或TS作为最佳变换,以及独立色度编码中是否存在非零系数。具体分为以下两种情况:

(1)当Cb和Cr分量都使用DCT-2或者当只有一个色度分量(Cb或Cr)具有非零系数并且色度分量选择DCT-2时,则JCCR模式仅检查DCT-2。类似地,当Cb和Cr分量都使用TS时,或者当只有一个色度分量具有非零系数并且分量选择TS时,JCCR模式仅检查TS。

(2)当Cb和Cr分量的选择变换不同时,即当一个选择DCT-2而另一个选择TS或反之时,JCCR对DCT-2和TS都进行测试。在这些情况下,在TS模式之前执行DCT-2模式的R-D检查,如果DCT-2的系数都为零,则跳过TS R-D检查。

TrQuant::TrQuant() : m_quant( nullptr )
{// allocate temporary buffers{m_invICT      = m_invICTMem + maxAbsIctMode;m_invICT[ 0]  = invTransformCbCr< 0>;m_invICT[ 1]  = invTransformCbCr< 1>;m_invICT[-1]  = invTransformCbCr<-1>;m_invICT[ 2]  = invTransformCbCr< 2>;m_invICT[-2]  = invTransformCbCr<-2>;m_invICT[ 3]  = invTransformCbCr< 3>;m_invICT[-3]  = invTransformCbCr<-3>;m_fwdICT      = m_fwdICTMem + maxAbsIctMode;m_fwdICT[ 0]  = fwdTransformCbCr< 0>;m_fwdICT[ 1]  = fwdTransformCbCr< 1>;m_fwdICT[-1]  = fwdTransformCbCr<-1>;m_fwdICT[ 2]  = fwdTransformCbCr< 2>;m_fwdICT[-2]  = fwdTransformCbCr<-2>;m_fwdICT[ 3]  = fwdTransformCbCr< 3>;m_fwdICT[-3]  = fwdTransformCbCr<-3>;}
}

invTransformCbCr函数如下,该函数主要是通过Cb(Cr)残差求出Cr(Cb)残差

template<int signedMode> void invTransformCbCr( PelBuf &resCb, PelBuf &resCr )
{Pel*  cb  = resCb.buf;Pel*  cr  = resCr.buf;for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride ){for( SizeType x = 0; x < resCb.width; x++ ){if      ( signedMode ==  1 )  { cr[x] =  cb[x] >> 1;  }else if ( signedMode == -1 )  { cr[x] = -cb[x] >> 1;  }else if ( signedMode ==  2 )  { cr[x] =  cb[x]; }else if ( signedMode == -2 )  { cr[x] = (cb[x] == -32768 && sizeof(Pel) == 2) ? 32767 : -cb[x]; }   // non-normative clipping to prevent 16-bit overflowelse if ( signedMode ==  3 )  { cb[x] =  cr[x] >> 1; }else if ( signedMode == -3 )  { cb[x] = -cr[x] >> 1; }}}
}

fwdTransformCbCr函数是通过ResCb和ResCr求出ResJointC

template<int signedMode> std::pair<int64_t,int64_t> fwdTransformCbCr( const PelBuf &resCb, const PelBuf &resCr, PelBuf& resC1, PelBuf& resC2 )
{const Pel*  cb  = resCb.buf;const Pel*  cr  = resCr.buf;Pel*        c1  = resC1.buf;Pel*        c2  = resC2.buf;int64_t     d1  = 0;int64_t     d2  = 0;for( SizeType y = 0; y < resCb.height; y++, cb += resCb.stride, cr += resCr.stride, c1 += resC1.stride, c2 += resC2.stride ){for( SizeType x = 0; x < resCb.width; x++ ){int cbx = cb[x], crx = cr[x];if      ( signedMode ==  1 ){c1[x] = Pel( ( 4*cbx + 2*crx ) / 5 );d1   += square( cbx - c1[x] ) + square( crx - (c1[x]>>1) );}else if ( signedMode == -1 ){c1[x] = Pel( ( 4*cbx - 2*crx ) / 5 );d1   += square( cbx - c1[x] ) + square( crx - (-c1[x]>>1) );}else if ( signedMode ==  2 ){c1[x] = Pel( ( cbx + crx ) / 2 );d1   += square( cbx - c1[x] ) + square( crx - c1[x] );}else if ( signedMode == -2 ){c1[x] = Pel( ( cbx - crx ) / 2 );d1   += square( cbx - c1[x] ) + square( crx + c1[x] );}else if ( signedMode ==  3 ){c2[x] = Pel( ( 4*crx + 2*cbx ) / 5 );d1   += square( cbx - (c2[x]>>1) ) + square( crx - c2[x] );}else if ( signedMode == -3 ){c2[x] = Pel( ( 4*crx - 2*cbx ) / 5 );d1   += square( cbx - (-c2[x]>>1) ) + square( crx - c2[x] );}else{d1   += square( cbx );d2   += square( crx );}}}return std::make_pair(d1,d2);
}

H.266/VVC技术学习:色度联合编码(JCCR)技术相关推荐

  1. H.266/VVC代码学习20:角度预测入口 / 特殊模式的PDPC技术(predIntraAng)

    1.predIntraAng函数 predIntraAng是帧内0~66这67种预测的入口.其中可细分为: 模式0:PLANAR模式 模式1:DC模式 模式2~66:角度模式 此函数在亮度预测和色度预 ...

  2. H.266/VVC代码学习21:帧内角度预测的实现 / 近对角模式的PDPC(xPredIntraAng)

    xPredIntraAng函数的作用是对任意大小的块和任意模式,如何将参考像素的值根据其模式的角度填充进每一个像素. 下图是basketball drill的一个16*16的块,其预测模式为10(偏斜 ...

  3. H.266/VVC代码学习17:帧内亮度预测的编解码(intra_luma_pred_modes)

    引--亮度预测:H.266/VVC代码学习5:VTM4.0帧内亮度预测代码(estIntraPredLumaQT) 一.结论: 亮度编解码根据MPM列表的值分为两个阶段: 1 亮度模式在MPM列表中: ...

  4. H.266/VVC代码学习:帧内预测之角度预测函数(predIntraAng、xPredIntraAng)

    predIntraAng函数 VTM中,帧内预测的角度预测的入口函数为predIntraAng函数,该函数主要是用于进行传统的帧内预测(Planar.DC.角度预测),然后对Planar和DC模式使用 ...

  5. H.266/VVC代码学习:xCompressCU函数

    xCompressCU函数是用来进行CU划分(递归调用自身)以及模式选择. 首先调用m_modeCtrl->initCULevel函数初始化模式选择列表,由堆栈控制,将当前CU可以划分的模式(四 ...

  6. H.266/VVC代码学习:MIP技术相关代码之initIntraMip函数

    initIntraMip函数主要是对参考像素进行下采样并为MIP矩阵乘法准备输入数据,函数结构如下: MIP根据块尺寸可以分为以下三种情况:   块尺寸 下采样后的边界长度 m_reducedBdry ...

  7. H.266/VVC代码学习32:VTM5.0解码端最上层函数

    解码部分的研究不像编码端那样需要精雕细琢,但如果想研究一个内容划分或选择模式等的最终结果是怎样,那么应该从解码端入手.下面让我们来学习解码端的框架及最上层的三个函数. 文章目录 1 main() 2 ...

  8. H.266/VVC代码学习:DC模式和Planar模式

    Planar模式和DC模式时两种特殊的角度模式,分别对应于模式号0和1. 一.DC模式 DC模式适用于大面积平坦区域,其预测值是通过计算左边和(或)上边参考像素的平均值获得的. 1.1.计算 DC模式 ...

  9. H.266/VVC变换量化部分内容总结

    变换 一.基础内容 VVC中使用了DCT-2变换.DST-7变换和DCT-8变换作为主变换:同时为了进一步提高变换的性能,VVC针对帧内预测残差的低频分量引入了不可分变换作为二次变换(低频不可分二次变 ...

最新文章

  1. Java 并发/多线程教程(四)-并发模型
  2. python做数据透视表_Python--数据透视表和交叉表、数据读取
  3. python打开文件报错无效序列_psycopg2.DataError:编码“UTF8”的字节序列无效:0xa0
  4. NDK学习笔记-JNI的引用
  5. api接口响应类型定义
  6. BeetleX网关非法Url请求拦截插件
  7. PhoneGap在Microsoft Visual Studio Express For Wi...
  8. 你很熟悉CSS,却没掌握这些CSS技巧
  9. PhoenixFramework自动化测试平台部署初始化说明
  10. 计算机辅助几何设计等值曲线,中国科学技术大学硕士专业:计算机辅助几何设计...
  11. VS2017透明背景和皮肤设置
  12. 可能是最详细的Win10+黑苹果双系统安装教程(For Dell 7580)
  13. win7新建ios开发环境
  14. android专业拍照软件,安卓最专业的拍照软件排行榜 优质滤镜相机软件推荐
  15. 为什么大部分人,会对南北经济“差距”产生误解?
  16. JavaScript之promise对象及ajax的使用
  17. 故事是如何改变人生的
  18. 安装gms 的拨号盘
  19. 哔哩哔哩轻视频怎么去水印
  20. 调整DOSBox的窗口大小:跨过三连坑

热门文章

  1. 测试流程和测试常用的案例
  2. zjoi 2008 杀蚂蚁
  3. Linux 查看目录下文件的详细信息
  4. 常用正则(持续更新)
  5. 编写一个C程序,运行时输出以下图形:
  6. 动手写prometheus的exporter-01-Gauge(仪表盘)
  7. 深入探索微信公众号开发:Java代码实现与最佳实践
  8. 安卓模拟器反编译获取微信小程序源码。
  9. React 生命周期、Hooks
  10. minecraft java版多少钱_Java版版本记录