• VVC代码阅读 帧内预测部分(1) xCheckRDCostIntra()函数(部分)


    VVC参考软件VTM6.0中变换的相关代码讲解与注释(一)_sky_Ryota的博客-CSDN博客

    VTM6变换算法小结(译自O2002)_Allen---Jiang的博客-CSDN博客

    H.266/VVC代码学习:xCheckRDCostIntra函数_涵小呆的博客-CSDN博客

    亮度预测函数前

    1. bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, bool adaptiveColorTrans)
    2. {
    3. double bestInterCost = m_modeCtrl->getBestInterCost();//最佳帧间代价
    4. double costSize2Nx2NmtsFirstPass = m_modeCtrl->getMtsSize2Nx2NFirstPassCost();//MTS不开启情况下的RDcost
    5. bool skipSecondMtsPass = m_modeCtrl->getSkipSecondMTSPass();//为true表示跳过测试除了第一个trGrp之外的情况
    6. const SPS& sps = *tempCS->sps;
    7. //为True表示测试MTS开启的情况
    8. const int maxSizeMTS = MTS_INTRA_MAX_CU_SIZE;//32
    9. uint8_t considerMtsSecondPass = ( sps.getUseIntraMTS() && isLuma( partitioner.chType ) && partitioner.currArea().lwidth() <= maxSizeMTS && partitioner.currArea().lheight() <= maxSizeMTS ) ? 1 : 0;
    10. //为1表示当前CU开启ISP
    11. bool useIntraSubPartitions = false;
    12. //色度分量最大允许RDcost
    13. double maxCostAllowedForChroma = MAX_DOUBLE;
    14. //当前CU的最佳模式
    15. const CodingUnit *bestCU = bestCS->getCU( partitioner.chType );
    16. Distortion interHad = m_modeCtrl->getInterHad();
    17. //一些参数设置
    18. double dct2Cost = MAX_DOUBLE;//不开启MTS且不开启LFNST情况下的RDcost
    19. double bestNonDCT2Cost = MAX_DOUBLE;//开启MTS或开启LFNST情况下的最佳RDcost
    20. //如果对应的trGrp中有测试的模式成为最佳模式,此为对应的trGrp的最佳RDcost
    21. double trGrpBestCost [ 4 ] = { MAX_DOUBLE, MAX_DOUBLE, MAX_DOUBLE, MAX_DOUBLE };
    22. double globalBestCost = MAX_DOUBLE;//如果有测试的模式成为最佳模式,此为最佳RDcost
    23. bool bestSelFlag [ 4 ] = { false, false, false, false };//如果对应的trGrp中有测试的模式成为最佳模式,此为true
    24. bool trGrpCheck [ 4 ] = { true, true, true, true };//如果对应的trGrp需要测试,此为true
    25. //对应trGrp要测试MTS中的哪些情况由下面两个变量决定
    26. int startMTSIdx [ 4 ] = { 0, 1, 2, 3 };
    27. int endMTSIdx [ 4 ] = { 0, 1, 2, 3 };
    28. //当前trGrp的最佳RDcost与不开启MTS且不开启LFNST情况下的RDcost的比例如果超过阈值,就会停止测试下一个trGrp。这个阈值就由trGrpStopThreshold决定
    29. double trGrpStopThreshold[ 3 ] = { 1.001, 1.001, 1.001 };
    30. int bestMtsFlag = 0;//如果有测试的模式成为最佳模式,此为最佳模式的mtsFlag
    31. int bestLfnstIdx = 0;//如果有测试的模式成为最佳模式,此为最佳模式的lfnstIdx
    32. //如果当前CU可以测试LFNST开启的情况,此为2否则就为0
    33. const int maxLfnstIdx = ( partitioner.isSepTree( *tempCS ) && partitioner.chType == CHANNEL_TYPE_CHROMA && ( partitioner.currArea().lwidth() < 8 || partitioner.currArea().lheight() < 8 ) )
    34. || ( partitioner.currArea().lwidth() > sps.getMaxTbSize() || partitioner.currArea().lheight() > sps.getMaxTbSize() ) ? 0 : 2;
    35. //为true表示跳过测试其余的LFNST的情况
    36. bool skipOtherLfnst = false;
    37. //要测试LFNST中的哪些情况由下面两个变量决定
    38. int startLfnstIdx = 0;
    39. int endLfnstIdx = sps.getUseLFNST() ? maxLfnstIdx : 0;
    40. //trGrp的数量
    41. int grpNumMax = sps.getUseLFNST() ? m_pcEncCfg->getMTSIntraMaxCand() : 1;
    42. m_modeCtrl->setISPWasTested(false);
    43. m_pcIntraSearch->invalidateBestModeCost();
    44. if (sps.getUseColorTrans() && !CS::isDualITree(*tempCS))
    45. {
    46. if ((m_pcEncCfg->getRGBFormatFlag() && adaptiveColorTrans) || (!m_pcEncCfg->getRGBFormatFlag() && !adaptiveColorTrans))
    47. {
    48. m_pcIntraSearch->invalidateBestRdModeFirstColorSpace();
    49. }
    50. }
    51. bool foundZeroRootCbf = false;/发现RootCbf为0的情况
    52. if (sps.getUseColorTrans()) //如果用了色彩转换
    53. {
    54. CHECK(tempCS->treeType != TREE_D || partitioner.treeType != TREE_D, "localtree should not be applied when adaptive color transform is enabled");
    55. CHECK(tempCS->modeType != MODE_TYPE_ALL || partitioner.modeType != MODE_TYPE_ALL, "localtree should not be applied when adaptive color transform is enabled");
    56. CHECK(adaptiveColorTrans && (CS::isDualITree(*tempCS) || partitioner.chType != CHANNEL_TYPE_LUMA), "adaptive color transform cannot be applied to dual-tree");
    57. }

    MTS:多变换核选择

    LFNST:低频不可分离变换

    trGrp:推测应该是代表一个过程,测试MTS和LFNST在不同情况下的模式。有很多个trGrp

    顶上第三个博客下评论:指的是MTS的DCT8和DST7的那四个组合,MTS_DST7_DST7、 MTS_DCT8_DST7、 MTS_DST7_DCT8、MTS_DCT8_DCT8。這四組變換都會對目前的CU block進行estIntraPredLumaQT函式,然後計算出最好的角度模式(0~67)

    for循环分trGrp测试

    1. for( int trGrpIdx = 0; trGrpIdx < grpNumMax; trGrpIdx++ )
    2. {
    3. //MTS的标志位设定
    4. const uint8_t startMtsFlag = trGrpIdx > 0;
    5. const uint8_t endMtsFlag = sps.getUseLFNST() ? considerMtsSecondPass : 0;
    6. if( ( trGrpIdx == 0 || ( !skipSecondMtsPass && considerMtsSecondPass ) ) && trGrpCheck[ trGrpIdx ] )
    7. {
    8. for( int lfnstIdx = startLfnstIdx; lfnstIdx <= endLfnstIdx; lfnstIdx++ )
    9. {
    10. for( uint8_t mtsFlag = startMtsFlag; mtsFlag <= endMtsFlag; mtsFlag++ )
    11. {
    12. if (sps.getUseColorTrans() && !CS::isDualITree(*tempCS))
    13. {
    14. m_pcIntraSearch->setSavedRdModeIdx(trGrpIdx*(NUM_LFNST_NUM_PER_SET * 2) + lfnstIdx * 2 + mtsFlag);
    15. }
    16. if (mtsFlag > 0 && lfnstIdx > 0)
    17. {
    18. continue;
    19. }
    20. //3) if interHad is 0, only try further modes if some intra mode was already better than inter
    21. if( sps.getUseLFNST() && m_pcEncCfg->getUsePbIntraFast() && !tempCS->slice->isIntra() && bestCU && CU::isInter( *bestCS->getCU( partitioner.chType ) ) && interHad == 0 )
    22. {
    23. continue;
    24. }
    25. tempCS->initStructData( encTestMode.qp );
    26. //根据area信息创建一个CU,并在下面信息填充
    27. CodingUnit &cu = tempCS->addCU( CS::getArea( *tempCS, tempCS->area, partitioner.chType ), partitioner.chType );
    28. //CU信息传递
    29. partitioner.setCUData( cu );
    30. cu.slice = tempCS->slice;
    31. cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );
    32. cu.skip = false;
    33. cu.mmvdSkip = false;
    34. cu.predMode = MODE_INTRA;
    35. cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
    36. cu.qp = encTestMode.qp;
    37. cu.lfnstIdx = lfnstIdx;
    38. cu.mtsFlag = mtsFlag;
    39. cu.ispMode = NOT_INTRA_SUBPARTITIONS;
    40. cu.colorTransform = adaptiveColorTrans;
    41. //根据CU添加PU
    42. CU::addPUs( cu );
    43. tempCS->interHad = interHad;
    44. true表示更新了最佳模式
    45. m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    46. bool validCandRet = false;
    47. //判断是否亮度分量
    48. if( isLuma( partitioner.chType ) )
    49. {
    50. //ISP uses the value of the best cost so far (luma if it is the fast version) to avoid test non-necessary subpartitions
    51. double bestCostSoFar = partitioner.isSepTree(*tempCS) ? m_modeCtrl->getBestCostWithoutSplitFlags() : bestCU && bestCU->predMode == MODE_INTRA ? bestCS->lumaCost : bestCS->cost;
    52. if (partitioner.isSepTree(*tempCS) && encTestMode.maxCostAllowed < bestCostSoFar)
    53. {
    54. bestCostSoFar = encTestMode.maxCostAllowed;
    55. }
    56. validCandRet = m_pcIntraSearch->estIntraPredLumaQT(cu, partitioner, bestCostSoFar, mtsFlag, startMTSIdx[trGrpIdx], endMTSIdx[trGrpIdx], (trGrpIdx > 0), !cu.colorTransform ? bestCS : nullptr);

    变换的部分先粗略看,可参考VTM10.0代码学习13:xCheckRDCostIntra()_柴门风雪夜的博客-CSDN博客

    addPUs()可参考之前写的addCU()函数

    m_bestModeUpdated:为true表示更新了最佳模式

    bestCostSoFar:检测当前tempCs是否为分离树,如果为true,则值为m_ComprCUCtxList中的bestCostWithoutSplitFlags。如果为false,则判断bestCU是否存在且preMode是否为MODE_INTRA。为true,则值为bestCS->lumaCost.为false,值为bestCS->Cost

    if语句:如果当前tempCs为分离树且当前测试模式的maxCostAllowed小于bestCostSoFar,则

    bestCostSoFar = maxCostAllowed

    然后就是亮度预测函数estIntraPredLumaQT()

    后面的之后再看

  • 相关阅读:
    综合项目实战--jenkins节点模式
    【力扣每日一题】2023.10.22 做菜顺序
    Java实现抽奖幸运儿
    【正点原子STM32连载】第十二章 SYSTEM文件夹介绍 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
    C和指针 第15章 输入/输出函数 15.14 流错误函数
    C# 方法参数out(实现int.Tyrparse()方法)
    论文阅读笔记 | 三维目标检测——PointNet++
    Promise
    rsync远程同步
    Hue在大数据生态圈的集成
  • 原文地址:https://blog.csdn.net/dfhg54/article/details/125482642