注意:本次代码运用的是encoder_intra_vtm的设置,所以GOP_size  只有一帧

   // store sub-picture numbers, sizes, and locations with a picturepcSlice->getPic()->subPictures.clear();for( int subPicIdx = 0; subPicIdx < pcPic->cs->pps->getNumSubPics(); subPicIdx++ ){pcSlice->getPic()->subPictures.push_back( pcPic->cs->pps->getSubPic( subPicIdx ) );//好像是根据序号,把子图片移动到队列末尾?}const VPS* vps = pcPic->cs->vps;//视频参数集int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx(pcPic->layerId);if (vps && !vps->getIndependentLayerFlag(layerIdx) && pcPic->cs->pps->getNumSubPics() > 1){CU::checkConformanceILRP(pcSlice);}xPicInitHashME( pcPic, pcSlice->getPPS(), rcListPic );if( m_pcCfg->getUseAMaxBT() ){if (!pcSlice->isIRAP()){int refLayer = pcSlice->getDepth();if (refLayer > 9){refLayer = 9;   // Max layer is 10}if( m_bInitAMaxBT && pcSlice->getPOC() > m_uiPrevISlicePOC ){::memset( m_uiBlkSize, 0, sizeof( m_uiBlkSize ) );::memset( m_uiNumBlk,  0, sizeof( m_uiNumBlk ) );m_bInitAMaxBT = false;}if( refLayer >= 0 && m_uiNumBlk[refLayer] != 0 ){picHeader->setSplitConsOverrideFlag(true);double dBlkSize = sqrt( ( double ) m_uiBlkSize[refLayer] / m_uiNumBlk[refLayer] );unsigned int newMaxBtSize = picHeader->getMaxBTSize(pcSlice->getSliceType(), CHANNEL_TYPE_LUMA);if( dBlkSize < AMAXBT_TH32 ){newMaxBtSize = 32;}else if( dBlkSize < AMAXBT_TH64 ){newMaxBtSize = 64;}else{newMaxBtSize = 128;}newMaxBtSize = Clip3(picHeader->getMinQTSize(pcSlice->getSliceType()), pcPic->cs->sps->getCTUSize(), newMaxBtSize);picHeader->setMaxBTSize(1, newMaxBtSize);m_uiBlkSize[refLayer] = 0;m_uiNumBlk [refLayer] = 0;}}else{if( m_bInitAMaxBT ){::memset( m_uiBlkSize, 0, sizeof( m_uiBlkSize ) );::memset( m_uiNumBlk,  0, sizeof( m_uiNumBlk ) );}m_uiPrevISlicePOC = pcSlice->getPOC();m_bInitAMaxBT = true;}bool identicalToSPS=true;const SPS* sps =pcSlice->getSPS();if (picHeader->getPicInterSliceAllowedFlag()){if (picHeader->getMinQTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMinQTSize(pcSlice->getSliceType()) ||picHeader->getMaxMTTHierarchyDepth(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxMTTHierarchyDepth() ||picHeader->getMaxBTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxBTSize() ||picHeader->getMaxTTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxTTSize()){identicalToSPS=false;}}if (identicalToSPS && picHeader->getPicIntraSliceAllowedFlag()){if (picHeader->getMinQTSize(I_SLICE) != sps->getMinQTSize(I_SLICE) ||picHeader->getMaxMTTHierarchyDepth(I_SLICE) != sps->getMaxMTTHierarchyDepthI() ||picHeader->getMaxBTSize(I_SLICE) != sps->getMaxBTSizeI() ||picHeader->getMaxTTSize(I_SLICE) != sps->getMaxTTSizeI()){identicalToSPS=false;}if (identicalToSPS && sps->getUseDualITree()){if (picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) ||picHeader->getMaxMTTHierarchyDepth(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxMTTHierarchyDepthIChroma() ||picHeader->getMaxBTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxBTSizeIChroma() ||picHeader->getMaxTTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxTTSizeIChroma()){identicalToSPS=false;}}}if (identicalToSPS){picHeader->setSplitConsOverrideFlag(false);}}

subPictures.clear():清空缓存并存放一个图片的子图片编号、大小和位置

getNumSubPics():设置m_numSubPics,已使用的子图片数量,必须与SPS相匹配。默认设置为0.       software_manual里有相关名词解释。

第一个if语句:看vps参数,得到m_generalLayerIdx,代表设置的分层层数。由layerId的值决定,最大64.

xPicInitHashME():初始化m_uiBlkSize,m_uiNumBlk并设置为0.

第二个if语句(2545~2640):查看是否使用AMaxBT(Adaptive maximal BT-size)这个技术,默认都使用。再看是什么帧.B,P帧有一个if语句,i帧是另一个if语句

memset用法详解(转)_luxuejuncarl的博客-CSDN博客

两个memset:初始化m_uiBlkSize,m_uiNumBlk并设置为0.Blk(BLOCK),

identicalToSPS:因为此时设置的全为I帧,所以帧内预测。这个参数也设置为true。

getPicIntraSliceAllowedFlag():slice帧内的一个标志。

maxBTSize[3]:允许的二叉树根节点最大尺寸.// 0: I slice luma; 1: P/B slice; 2: I slice chroma

if语句(picHeader->getMaxBTSize(I_SLICE) != sps->getMaxBTSizeI()):如果从图片头信息中得到的maxBTSize和从sps中得到的maxBTSize不同,则将identicalToSPS设置为false。注意这里是getMaxBTSizeI(),得到的是I slice 的亮度分量的maxBTSize。

getUseDualITree():dualtree(Enables or disables the use of separate QTBT trees for intra slice luma and chroma channel types.),即亮色度具有不同的编码树结构

if语句(picHeader->getMaxBTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxBTSizeIChroma()):如果从图片头信息中得到的maxBTSize和从sps中得到的maxBTSize不同,则将identicalToSPS设置为false.这里得到的是I slice 的色度分量的maxBTSize。

setSplitConsOverrideFlag():设置m_splitConsOverrideFlag为false。划分受限操控标志,表示现在划分不受限

 //  Slice info. refinementif ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) ){pcSlice->setSliceType ( P_SLICE );}xUpdateRasInit( pcSlice );if (pcSlice->getPendingRasInit() || pcSlice->isIRAP()){// this ensures that independently encoded bitstream chunks can be combined to bit-equalpcSlice->setEncCABACTableIdx( pcSlice->getSliceType() );}else{pcSlice->setEncCABACTableIdx( m_pcSliceEncoder->getEncCABACTableIdx() );}if (pcSlice->getSliceType() == B_SLICE){bool bLowDelay = true;int  iCurrPOC  = pcSlice->getPOC();int iRefIdx = 0;for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++){if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC ){bLowDelay = false;}}for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++){if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC ){bLowDelay = false;}}pcSlice->setCheckLDC(bLowDelay);}else{pcSlice->setCheckLDC(true);}

第一个if语句:修正slice的类型,如果检验为B slice且无参考帧列表1,则修正为P slice

xUpdateRasInit():设置m_lastRasPoc和slice的m_pendingRasInit。m_lastRasPoc表示按编码顺序之前最近的IRAP帧的POC,包括自身。m_pendingRasInit和下面的if分支有关。

如果当前slice的poc序号大于m_lastRasPoc,代表当前不是I帧,则把m_pendingRasInit设为true。否则m_lastRasPoc设为当前帧的poc序号。

第二个if语句:如果m_pendingRasInit为true或当前帧为i帧,则执行setEncCABACTableIdx()。

setEncCABACTableIdx():好像是关于自适应算术编码的一个确保机制,之后再修改

第三个if语句:与low _delay模式有关,之后再看

    pcSlice->setRefPOCList();pcSlice->setList1IdxToList0Idx();if (m_pcEncLib->getTMVPModeId() == 2){if (iGOPid == 0) // first picture in SOP (i.e. forward B){picHeader->setEnableTMVPFlag(0);}else{// Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0.picHeader->setEnableTMVPFlag(1);}}else if (m_pcEncLib->getTMVPModeId() == 1){picHeader->setEnableTMVPFlag(1);}else{picHeader->setEnableTMVPFlag(0);}// disable TMVP when current picture is the only ref pictureif (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag()){picHeader->setEnableTMVPFlag(0);//当前图片是唯一的参考图片时禁用TMVP}if( pcSlice->getSliceType() != I_SLICE && picHeader->getEnableTMVPFlag() ){int colRefIdxL0 = -1, colRefIdxL1 = -1;for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); refIdx++ ){CHECK( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->unscaledPic == nullptr, "unscaledPic is not set for L0 reference picture" );if( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->isRefScaled( pcSlice->getPPS() ) == false ){colRefIdxL0 = refIdx;break;}}if( pcSlice->getSliceType() == B_SLICE ){for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); refIdx++ ){CHECK( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->unscaledPic == nullptr, "unscaledPic is not set for L1 reference picture" );if( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->isRefScaled( pcSlice->getPPS() ) == false ){colRefIdxL1 = refIdx;break;}}}if( colRefIdxL0 >= 0 && colRefIdxL1 >= 0 ){const Picture *refPicL0 = pcSlice->getRefPic( REF_PIC_LIST_0, colRefIdxL0 );if( !refPicL0->slices.size() ){refPicL0 = refPicL0->unscaledPic;}const Picture *refPicL1 = pcSlice->getRefPic( REF_PIC_LIST_1, colRefIdxL1 );if( !refPicL1->slices.size() ){refPicL1 = refPicL1->unscaledPic;}CHECK( !refPicL0->slices.size(), "Wrong L0 reference picture" );CHECK( !refPicL1->slices.size(), "Wrong L1 reference picture" );const uint32_t uiColFromL0 = refPicL0->slices[0]->getSliceQp() > refPicL1->slices[0]->getSliceQp();picHeader->setPicColFromL0Flag( uiColFromL0 );pcSlice->setColFromL0Flag( uiColFromL0 );pcSlice->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );picHeader->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );}else if( colRefIdxL0 < 0 && colRefIdxL1 >= 0 ){picHeader->setPicColFromL0Flag( false );pcSlice->setColFromL0Flag( false );pcSlice->setColRefIdx( colRefIdxL1 );picHeader->setColRefIdx( colRefIdxL1 );}else if( colRefIdxL0 >= 0 && colRefIdxL1 < 0 ){picHeader->setPicColFromL0Flag( true );pcSlice->setColFromL0Flag( true );pcSlice->setColRefIdx( colRefIdxL0 );picHeader->setColRefIdx( colRefIdxL0 );}else{picHeader->setEnableTMVPFlag( 0 );}}

setRefPOCList():设置slice的m_aiRefPOCList,表示参考帧列表中对应帧的POC。

几个函数解释(在 B 帧时记得验证一下)_青椒鸡汤的博客-CSDN博客

setList1IdxToList0Idx():设置slice的m_list1IdxToList0Idx,含义是RPL1的帧如果同时存在RPL0中,则为帧在RPL0中的Index,否则为-1。等后面再验证

第一个和第二个if分支:设置PictureHeader的m_enableTMVPFlag,表示是否开启TMVP。默认设置sbTMVP = 1.

setEnableTMVPFlag():设置m_enableTMVPFlag,是否启用时间运动矢量预测

if( pcSlice->getSliceType() != I_SLICE:进行有关TMVP的非I帧的设置,没仔细看

#if GDR_ENABLEDPicHeader *picHeader = new PicHeader;*picHeader = *pcPic->cs->picHeader;pcSlice->scaleRefPicList(scaledRefPic, picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false);picHeader = pcPic->cs->picHeader;
#elsepcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
#endif// set adaptive search range for non-intra-slicesif (m_pcCfg->getUseASR() && !pcSlice->isIntra()){m_pcSliceEncoder->setSearchRange(pcSlice);//如果开启ASR,设置运动搜索范围}bool bGPBcheck=false;//为true表示RPL0和RPL1相同if ( pcSlice->getSliceType() == B_SLICE){if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ){bGPBcheck=true;int i;for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ ){if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) ){bGPBcheck=false;break;}}}}if(bGPBcheck){picHeader->setMvdL1ZeroFlag(true);}else{picHeader->setMvdL1ZeroFlag(false);}if ( pcSlice->getSPS()->getUseSMVD() && pcSlice->getCheckLDC() == false&& picHeader->getMvdL1ZeroFlag() == false){int currPOC = pcSlice->getPOC();int forwardPOC = currPOC;int backwardPOC = currPOC;int ref = 0, refIdx0 = -1, refIdx1 = -1;// search nearest forward POC in List 0for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ ){int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_0, ref)->longTerm;if ( poc < currPOC && (poc > forwardPOC || refIdx0 == -1) && !isRefLongTerm ){forwardPOC = poc;refIdx0 = ref;}}// search nearest backward POC in List 1for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ ){int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_1, ref)->longTerm;if ( poc > currPOC && (poc < backwardPOC || refIdx1 == -1) && !isRefLongTerm ){backwardPOC = poc;refIdx1 = ref;}}if ( !(forwardPOC < currPOC && backwardPOC > currPOC) ){forwardPOC = currPOC;backwardPOC = currPOC;refIdx0 = -1;refIdx1 = -1;// search nearest backward POC in List 0for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ ){int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_0, ref)->longTerm;if ( poc > currPOC && (poc < backwardPOC || refIdx0 == -1) && !isRefLongTerm ){backwardPOC = poc;refIdx0 = ref;}}// search nearest forward POC in List 1for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ ){int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_1, ref)->longTerm;if ( poc < currPOC && (poc > forwardPOC || refIdx1 == -1) && !isRefLongTerm ){forwardPOC = poc;refIdx1 = ref;}}}if ( forwardPOC < currPOC && backwardPOC > currPOC ){pcSlice->setBiDirPred( true, refIdx0, refIdx1 );}else{pcSlice->setBiDirPred( false, -1, -1 );}}else{pcSlice->setBiDirPred( false, -1, -1 );}if( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL && m_pcCfg->getRprRASLtoolSwitch() ){pcSlice->setDisableLmChromaCheck( true );picHeader->setDmvrDisabledFlag( true );xUpdateRPRtmvp( picHeader, pcSlice );}

scaleRefPicList():如果参考帧的分辨率和编码帧的不一致,则要进行缩放

getUseASR():adaptive search range,自适应搜索范围,默认关闭

第一个if语句:当ASR开启且不是I帧时,设置运动搜索范围

第二个if语句:查验当为B 帧时,参考帧列表0和1是否相同,相同则bGPBcheck=true

if(bGPBcheck):如果参考帧列表0和1相同,设置PictureHeader的m_mvdL1ZeroFlag,为true表示不用传输RPL1的MVD

第三个if分支:设置是否开启SMVD,以及前后向参考帧在RPL中的Index。SMVD默认关闭

最后一个if语句:设置一些标志

【八】 H.266/vvc中对称MVD模式(SMVD)_Cohen_ina的博客-CSDN博客

H.266/VVC帧间预测总结_涵小呆的博客-CSDN博客_vvc帧间

double lambda            = 0.0;//定义lambda,并且赋初值int actualHeadBits       = 0;//写入码流中的slice header的比特数(可能包括picture header)int actualTotalBits      = 0;//写入码流中的总比特数int estimatedBits        = 0;//预测比特数int tmpBitsBeforeWriting = 0;xPicInitRateControl(estimatedBits, iGOPid, lambda, pcPic, pcSlice);//初始化码率控制uint32_t uiNumSliceSegments = 1;pcSlice->setDefaultClpRng(*pcSlice->getSPS());//设置slice的m_clpRngs,有关于clip// Allocate some coders, now the number of tiles are known.const uint32_t numberOfCtusInFrame = pcPic->cs->pcv->sizeInCtus;//一帧内CTU的数量const int numSubstreamsColumns = pcSlice->getPPS()->getNumTileColumns();//一般为1const int numSubstreamRows     = pcSlice->getSPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->cs->pcv->heightInCtus : (pcSlice->getPPS()->getNumTileRows());//一般为1const int numSubstreams        = std::max<int> (numSubstreamRows * numSubstreamsColumns, (int) pcPic->cs->pps->getNumSlicesInPic());//一帧内substreams的数量,一般为1std::vector<OutputBitstream> substreamsOut(numSubstreams);//substreams的输出buffer

可参考  HEVC码率控制代码追踪(一)(HEVC code tracing-Rate control)_yang-彧的博客-CSDN博客

actualTotalBits:写入码流中的总比特数

actualHeadBits:写入码流中的slice header的比特数(可能包括picture header)

xPicInitRateControl:初始化码率控制,虽然cfg中默认不开,但还是提一下方便以后找

uiNumSliceSegments:slices的数量

setDefaultClpRng:设置slice的m_clpRngs,有关于clip

一个slice会形成一个stream,然后封装在VCL-NALU中。在形成stream之前会先形成substreams然后再合成stream。如何划分substreams和slice划分、tile划分、是否开启WaveFrontSynchro都有关系

getNumTileColumns():得到tile单元的列数

getEntropyCodingSyncEnabledFlag():WPP的标志。默认关闭


#if ENABLE_QPApcPic->m_uEnerHpCtu.resize (numberOfCtusInFrame);pcPic->m_iOffsetCtu.resize (numberOfCtusInFrame);
#if ENABLE_QPA_SUB_CTUif (pcSlice->getPPS()->getUseDQP() && pcSlice->getCuQpDeltaSubdiv() > 0){const PreCalcValues &pcv = *pcPic->cs->pcv;const unsigned   mtsLog2 = (unsigned)floorLog2(std::min (pcPic->cs->sps->getMaxTbSize(), pcv.maxCUWidth));pcPic->m_subCtuQP.resize ((pcv.maxCUWidth >> mtsLog2) * (pcv.maxCUHeight >> mtsLog2));}
#endif
#endifif (pcSlice->getSPS()->getSAOEnabledFlag()){pcPic->resizeSAO( numberOfCtusInFrame, 0 );pcPic->resizeSAO( numberOfCtusInFrame, 1 );}// it is used for signalling during CTU mode decision, i.e. before ALF processingif( pcSlice->getSPS()->getALFEnabledFlag() ){pcPic->resizeAlfCtuEnableFlag( numberOfCtusInFrame );pcPic->resizeAlfCtuAlternative( numberOfCtusInFrame );pcPic->resizeAlfCtbFilterIndex(numberOfCtusInFrame);}bool decPic = false;bool encPic = false;// test if we can skip the picture entirely or decode instead of encodingtrySkipOrDecodePicture( decPic, encPic, *m_pcCfg, pcPic, m_pcEncLib->getApsMap() );

这几个函数是关于一些新技术还有SAO(采样点自适应偏移),ALF(环路滤波)的标志等设定

pcPic->cs->slice = pcSlice; // please keep this
#if ENABLE_QPAif (pcSlice->getPPS()->getSliceChromaQpFlag() && CS::isDualITree (*pcSlice->getPic()->cs) && !m_pcCfg->getUsePerceptQPA() && (m_pcCfg->getSliceChromaOffsetQpPeriodicity() == 0))
#elseif (pcSlice->getPPS()->getSliceChromaQpFlag() && CS::isDualITree (*pcSlice->getPic()->cs))
#endif{// overwrite chroma qp offset for dual treepcSlice->setSliceChromaQpDelta(COMPONENT_Cb, m_pcCfg->getChromaCbQpOffsetDualTree());pcSlice->setSliceChromaQpDelta(COMPONENT_Cr, m_pcCfg->getChromaCrQpOffsetDualTree());if (pcSlice->getSPS()->getJointCbCrEnabledFlag()){pcSlice->setSliceChromaQpDelta(JOINT_CbCr, m_pcCfg->getChromaCbCrQpOffsetDualTree());}m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp());}xPicInitLMCS(pcPic, picHeader, pcSlice);//进行LMCS的初始化if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ ){picHeader->setExplicitScalingListEnabledFlag( true );pcSlice->setExplicitScalingListUsed( true );int apsId = std::min<int>( 7, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) );picHeader->setScalingListAPSId( apsId );ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap();APS*  scalingListAPS = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );assert( scalingListAPS != NULL );picHeader->setScalingListAPS( scalingListAPS );}pcPic->cs->picHeader->setPic(pcPic);//设置变量m_valid,表明图片头信息是否正确pcPic->cs->picHeader->setValid();//设置指针变量 m_pcPic,接收指向图片的指针变量pcPicif(pcPic->cs->sps->getFpelMmvdEnabledFlag()){// cannot set ph_fpel_mmvd_enabled_flag at slice level - need new picture-level version of checkDisFracMmvd algorithm?// m_pcSliceEncoder->checkDisFracMmvd( pcPic, 0, numberOfCtusInFrame );bool useIntegerMVD = (pcPic->lwidth()*pcPic->lheight() > 1920 * 1080);pcPic->cs->picHeader->setDisFracMMVD( useIntegerMVD );}if (pcSlice->getSPS()->getJointCbCrEnabledFlag()){m_pcSliceEncoder->setJointCbCrModes(*pcPic->cs, Position(0, 0), pcPic->cs->area.lumaSize());}
LMCSEnable:Enables or disables the use of LMCS (luma mapping with chroma scaling).
 xPicInitLMCS():初始化LMCS
第一个if语句:是否使用缩放列表(ScalingList),默认设置为0
getFpelMmvdEnabledFlag():设置m_fpelMmvdEnabledFlag标志,表明是否开启MMVD(merge mode with motion vector difference)
第二个if语句:推测如果图片的级别(level)不够,会设置useIntegerMVD为false,不使用MMVD
getJointCbCrEnabledFlag():JointCbCr(the joint coding of chroma residuals)色度残差联合编码的标志
  if (!pcSlice->getSPS()->getSpsRangeExtension().getReverseLastSigCoeffEnabledFlag() || pcSlice->getSliceQp() > 12){pcSlice->setReverseLastSigCoeffFlag(false);}else{/*for RA serial and parallel alignment start*/if (m_pcCfg->getIntraPeriod() > 1){if (pcSlice->isIntra()){m_cnt_right_bottom = 0;}if ((pocCurr % m_pcCfg->getIntraPeriod()) <= m_pcCfg->getGOPSize() && iGOPid == 0 && !pcSlice->isIntra()){m_cnt_right_bottom = m_cnt_right_bottom_i;}}/*for RA serial and parallel alignment end*/pcSlice->setReverseLastSigCoeffFlag(m_cnt_right_bottom >= 0);}

setReverseLastSigCoeffFlag():设置m_reverseLastSigCoeffFlag,默认为false。

ReverseLastSigCoeff        When true, enable reverse last signifificant coeffificient postion in RRC.
if( encPic )// now compress (trial encode) the various slice segments (slices, and dependent slices){DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "poc", pocCurr ) ) );const std::vector<uint16_t> sliceLosslessArray = *(m_pcCfg->getSliceLosslessArray());bool mixedLossyLossless = m_pcCfg->getMixedLossyLossless();if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING){pcPic->fillSliceLossyLosslessArray(sliceLosslessArray, mixedLossyLossless);}for(uint32_t sliceIdx = 0; sliceIdx < pcPic->cs->pps->getNumSlicesInPic(); sliceIdx++ ){pcSlice->setSliceMap( pcPic->cs->pps->getSliceMap( sliceIdx ) );if (pcSlice->getSPS()->getSpsRangeExtension().getTSRCRicePresentFlag() && (pcPic->cs->pps->getNumSlicesInPic() == 1)){if (!pcSlice->isIntra()){int nextRice = 1;if (m_preIPOC < pocCurr){for (int idx = 0; idx < MAX_TSRC_RICE; idx++){m_riceBit[idx][0] = m_riceBit[idx][1];}m_preQP[0] = m_preQP[1];m_preIPOC = MAX_INT;}if (m_preQP[0] != pcSlice->getSliceQp()){m_riceBit[pcSlice->get_tsrc_index()][0] = (int) (m_riceBit[pcSlice->get_tsrc_index()][0] * 9 / 10);}for (int idx = 2; idx < 9; idx++){if (m_riceBit[idx - 2][0] > m_riceBit[idx - 1][0]){nextRice = idx;}else{m_riceBit[idx - 1][0] = m_riceBit[idx - 2][0];}m_riceBit[idx - 2][0] = 0;}m_riceBit[7][0] = 0;pcSlice->set_tsrc_index(nextRice - 1);}else{m_preIPOC = pocCurr;m_preQP[0] = MAX_INT;          m_preQP[1] = pcSlice->getSliceQp();for (int idx = 0; idx < MAX_TSRC_RICE; idx++){m_riceBit[idx][0] = 0;}}for (int idx = 0; idx < MAX_TSRC_RICE; idx++){pcSlice->setRiceBit(idx, m_riceBit[idx][0]);}}if( pcPic->cs->pps->getRectSliceFlag() ){Position firstCtu;firstCtu.x = pcSlice->getFirstCtuRsAddrInSlice() % pcPic->cs->pps->getPicWidthInCtu();//SLICE中第一个CTU的位置firstCtu.y = pcSlice->getFirstCtuRsAddrInSlice() / pcPic->cs->pps->getPicWidthInCtu();int subPicIdx = NOT_VALID;//为后面check函数初始化赋值for( int sp = 0; sp < pcPic->cs->pps->getNumSubPics(); sp++ ){if( pcPic->cs->pps->getSubPic( sp ).containsCtu( firstCtu ) ){subPicIdx = sp;break;}}CHECK( subPicIdx == NOT_VALID, "Sub-picture was not found" );pcSlice->setSliceSubPicId( pcPic->cs->pps->getSubPic( subPicIdx ).getSubPicID() );}

encPic:encode picture ,在前面的trySkipOrDecodePicture()变成了true.

现在压缩(试编码)各种片段(片和相关片)
getSliceLosslessArray():返回一个无损编码片的数组m_sliceLosslessArray
getMixedLossyLossless():启用混合有损/无损编码,默认为false
getCostMode():COSTMODE是一个枚举函数,表示编码方式。
默认为COST_STANDARD_LOSSY   
for循环:把图片中的每一个slice,以光栅扫描的顺序,扫描slice中的每一个CTU,得到每个ctu的地址。
getTSRCRicePresentFlag():设置m_tsrcRicePresentFlag,默认为false。TSRCRicePresent 技术
getRectSliceFlag():矩形模式slice的标志。

列表中包含矩形模式slice下左上角的CTU RS地址,右下角的CTU RS地址。RS代表Rectangular slice。

getPicWidthInCtu():得到m_picWidthInCtu,应该是一帧图像一行包含CTU个数。在encodectus()函数中可体现出

firstCtu.x:得到矩形模式SLICE中第一个CTU的X地址

H.266/VVC的编码结构和块划分_涵小呆的博客-CSDN博客
推荐看VVC正式标准里第21页,有对subicture的更准确解释.一个subpicture可由一个或多个slice组成
getSubPic():m_subPics[idx]是按顺序存储子图片数据的一个表,idx为调用对应子图片的编号
containsCtu():m_subPicCtuTopLeftX,CTU结构中一个子图片的左上角CTU的水平位置。同理可得m_subPicCtuTopLeftY。如果这个CTU的x,y在这个子图宽度,长度范围内,则返回一个true
for循环:遍历每一个子图片,检测每个子图中的第一个CTU是否在子图的范围里,如果在,则把当前序号即为这个子图的索引号。
否则运行check,显示错误
 if (pcPic->cs->sps->getUseLmcs()){pcSlice->setLmcsEnabledFlag(picHeader->getLmcsEnabledFlag());if (pcSlice->getSliceType() == I_SLICE){//reshape original signalif(m_pcCfg->getGopBasedTemporalFilterEnabled()){pcPic->getOrigBuf().copyFrom(pcPic->getFilteredOrigBuf());}else{pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());}if (pcSlice->getLmcsEnabledFlag()){pcPic->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getFwdLUT());m_pcReshaper->setSrcReshaped(true);m_pcReshaper->setRecReshaped(true);}else{m_pcReshaper->setSrcReshaped(false);m_pcReshaper->setRecReshaped(false);}}}

getUseLmcs():使用LMCS

LMCS设置一些参数,先跳过

H.266/VVC代码学习:普通量化和率失真优化量化(RDOQ)_涵小呆的博客-CSDN博客
bool isLossless = false; //关闭无损编码if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING){isLossless = pcPic->losslessSlice(sliceIdx);}m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);if( pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic( REF_PIC_LIST_0, 0 )->subPictures.size() > 1 ){clipMv = clipMvInSubpic;m_pcEncLib->getInterSearch()->setClipMvInSubPic(true);}else{clipMv = clipMvInPic;m_pcEncLib->getInterSearch()->setClipMvInSubPic(false);}m_pcSliceEncoder->precompressSlice( pcPic );m_pcSliceEncoder->compressSlice   ( pcPic, false, false );

前两个if语句:与无损编码设置有关,跳过

precompressSlice():检查deltaQP,如果还没使用,直接return

【笔记】HEVC 编码标准(六)——量化_lock。的博客-CSDN博客

compressSlice():进入compressSlice()

VVC代码阅读(2)compressGOP函数(2)相关推荐

  1. VVC 代码阅读 compressCtu()函数

    void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr ...

  2. VVC代码阅读 xCheckModeSplit()函数 (中间CABAC还没看)最后代码还没看完

    //当前测试qpconst int qp = encTestMode.qp;//当前sliceconst Slice &slice = *tempCS->slice;// 之前的QPco ...

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

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

  4. 代码阅读 | torch.sort函数

    知识点https://blog.csdn.net/u012495579/article/details/106117511网友讲得非常清晰了. 代码如下: lengths = [17,17,19,23 ...

  5. VTM3.0代码阅读:xDeriveCUMV函数

    xDeriveCUMV函数根据解码得到的预测参数数据,计算得到mv. 函数内根据解码得到的各个模式的数据,获取到MMVD.三角预测.AffineMerge.普通merge.AffineME.普通int ...

  6. VTM3.0代码阅读:xEstimateMvPredAMVP函数

    AMVP运用于inter_ME模式的时候. xEstimateMvPredAMVP进行AMVP,获得当前pu的相邻运动信息,构建AMVP列表,最终选择出最优的MVP.AMVP最终获得的MVP作为ME的 ...

  7. VVC/H.266代码阅读(VTM8.0)(三. Slice到CTU的处理 )

    本文是本系列的第三篇博客,内容是分析从Slice到CTU的处理代码. 该系列相关博客为: VVC/H.266代码阅读(VTM8.0)(一. NALU提取) VVC/H.266代码阅读(VTM8.0)( ...

  8. compressGOP函数代码跟踪

    之前的学习中对encode函数进行了跟踪解读,在里面调用了compressGOP函数(代码太多了,看完得猴年马月,要人命,对付一下对付一下!),看到这个代码名字就联想到视频的编码过程了吧,视频先分成G ...

  9. ORB-SLAM2代码阅读笔记(五):Tracking线程3——Track函数中单目相机初始化

    Table of Contents 1.特征点匹配相关理论简介 2.ORB-SLAM2中特征匹配代码分析 (1)Tracking线程中的状态机 (2)单目相机初始化函数MonocularInitial ...

最新文章

  1. 【php】【psr】psr2 编码风格规范
  2. linux 错误日志 __ratelimit: XXX callbacks suppressed 原因
  3. python 基于UDP协议的socket 报错:OSError: [WinError 10049] 在其上下文中,该请求的地址无效(绑定的ip要跟本地ip对应)
  4. 数据湖分析如何面向对象存储OSS进行优化?
  5. Java解析Excel工具类(兼容xls和xlsx)
  6. android merge的作用,Android学习手记-merge
  7. MySQL分页查询语句
  8. 1910140852linux安装g
  9. 原型模式(Prototype)以及深浅复制
  10. element ui输入地内容明明符合规则还是校验报错
  11. 微信小程序;AI智能配音助手
  12. 中国大学慕课python答案第七章_中国大学慕课moocPython 语言程序设计mooc题库答案查询...
  13. org.gjt.mm.mysql.Driver与com.mysql.jdbc.Driver区别
  14. Eqs POJ - 1840
  15. 在腾讯实习一年,我学到了什么
  16. python展开阅读全文_展开阅读全文 js 爬虫操作
  17. jedis 源码阅读二——jedisPool
  18. 网关服务Kong和konga介绍安装使用教程
  19. Shopee开店不懂英语怎么办?
  20. cocos2d-x 颜色混合

热门文章

  1. 嫦娥二号没有拍到美国登月痕迹
  2. 【国产FPGA】国产FPGA搭建图像处理平台
  3. Python 国内镜像
  4. 上海python招聘微信群_Python之微信-微信群发
  5. 做微信还是做APP:两种创业的不同风险
  6. 猫盘用服务器硬盘,猫盘硬盘数据的转移具体方法步骤
  7. h5开启摄像头拍照+腾讯云接口人脸验证
  8. 计算机常用键盘有几个键失灵,电脑键盘忽然有几个键失灵了
  9. dnf压爆服务器挑战网站,DNF手游压爆服务器挑战网址分享
  10. Maven工程错误 之 Failure to transfer org.codehaus.plexus:plexus-archiver:pom:1.0