VTM10.0帧内之CCLM技术
Posted 神遁克里苏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VTM10.0帧内之CCLM技术相关的知识,希望对你有一定的参考价值。
为了减少分量间的冗余,提出分量间线性模型预测技术,基本思想是假设亮度分量和色度分量间存在某种线性关系,根据此线性关系实现亮度分量到色度分量的预测。
VVC中CCLM步骤如下:
1.使用特定位置的四个点。
- 对同位亮度块的 上述4个位置 以及 块内的所有 亮度样本进行下采样以获得和色度样本一一对应的亮度样本。以CCLM为例:
VTM10.0亮度下采样的代码:
用于生成包括参考像素和块内像素的下采样亮度值。
// LumaRecPixels 获得亮度的重建值
void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chromaArea)
int iDstStride = 0;
Pel* pDst0 = 0;
int curChromaMode = pu.intraDir[1];
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
//如果是CCLM_L模式或者是CCLM_T模式
iDstStride = 2 * MAX_CU_SIZE + 1;
pDst0 = m_pMdlmTemp + iDstStride + 1;//m_pMdlmTemp应该是指向左上方的点,加上了iDstStride+1后,指向块内第一个点
else
//CCLM模式
iDstStride = MAX_CU_SIZE + 1;
pDst0 = m_piTemp + iDstStride + 1; //MMLM_SAMPLE_NEIGHBOR_LINES;
//assert 420 chroma subsampling
CompArea lumaArea = CompArea( COMPONENT_Y, pu.chromaFormat, chromaArea.lumaPos(), recalcSize( pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, chromaArea.size() ) );//needed for correct pos/size (4x4 Tus)
CHECK(lumaArea.width == chromaArea.width && CHROMA_444 != pu.chromaFormat, "");
CHECK(lumaArea.height == chromaArea.height && CHROMA_444 != pu.chromaFormat && CHROMA_422 != pu.chromaFormat, "");
//获取色度块的长和宽
const SizeType uiCWidth = chromaArea.width;
const SizeType uiCHeight = chromaArea.height;
//获取重建的亮度
const CPelBuf Src = pu.cs->picture->getRecoBuf( lumaArea );
Pel const* pRecSrc0 = Src.bufAt( 0, 0 );
int iRecStride = Src.stride;
int logSubWidthC = getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, pu.chromaFormat);
int logSubHeightC = getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, pu.chromaFormat);
int iRecStride2 = iRecStride << logSubHeightC;
const CodingUnit& lumaCU = isChroma( pu.chType ) ? *pu.cs->picture->cs->getCU( lumaArea.pos(), CH_L ) : *pu.cu;
const CodingUnit& cu = *pu.cu;
const CompArea& area = isChroma( pu.chType ) ? chromaArea : lumaArea;
const uint32_t uiTuWidth = area.width;
const uint32_t uiTuHeight = area.height;
int iBaseUnitSize = ( 1 << MIN_CU_LOG2 );
const int iUnitWidth = iBaseUnitSize >> getComponentScaleX( area.compID, area.chromaFormat );
const int iUnitHeight = iBaseUnitSize >> getComponentScaleY(area.compID, area.chromaFormat);
const int iTUWidthInUnits = uiTuWidth / iUnitWidth;
const int iTUHeightInUnits = uiTuHeight / iUnitHeight;
const int iAboveUnits = iTUWidthInUnits;
const int iLeftUnits = iTUHeightInUnits;
const int chromaUnitWidth = iBaseUnitSize >> getComponentScaleX(COMPONENT_Cb, area.chromaFormat);
const int chromaUnitHeight = iBaseUnitSize >> getComponentScaleY(COMPONENT_Cb, area.chromaFormat);
const int topTemplateSampNum = 2 * uiCWidth; // for MDLM, the number of template samples is 2W or 2H.
const int leftTemplateSampNum = 2 * uiCHeight;
assert(m_topRefLength >= topTemplateSampNum);
assert(m_leftRefLength >= leftTemplateSampNum);
const int totalAboveUnits = (topTemplateSampNum + (chromaUnitWidth - 1)) / chromaUnitWidth;
const int totalLeftUnits = (leftTemplateSampNum + (chromaUnitHeight - 1)) / chromaUnitHeight;
const int totalUnits = totalLeftUnits + totalAboveUnits + 1;
const int aboveRightUnits = totalAboveUnits - iAboveUnits;
const int leftBelowUnits = totalLeftUnits - iLeftUnits;
int avaiAboveRightUnits = 0;
int avaiLeftBelowUnits = 0;
bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];
memset(bNeighborFlags, 0, totalUnits);
bool aboveIsAvailable, leftIsAvailable;
int availlableUnit = isLeftAvailable(isChroma(pu.chType) ? cu : lumaCU, toChannelType(area.compID), area.pos(),
iLeftUnits, iUnitHeight, (bNeighborFlags + iLeftUnits + leftBelowUnits - 1));
leftIsAvailable = availlableUnit == iTUHeightInUnits;
availlableUnit = isAboveAvailable(isChroma(pu.chType) ? cu : lumaCU, toChannelType(area.compID), area.pos(),
iAboveUnits, iUnitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + 1));
aboveIsAvailable = availlableUnit == iTUWidthInUnits;
if (leftIsAvailable) // if left is not available, then the below left is not available
avaiLeftBelowUnits = isBelowLeftAvailable(isChroma(pu.chType) ? cu : lumaCU, toChannelType(area.compID), area.bottomLeftComp(area.compID), leftBelowUnits, iUnitHeight, (bNeighborFlags + leftBelowUnits - 1));
if (aboveIsAvailable) // if above is not available, then the above right is not available.
avaiAboveRightUnits = isAboveRightAvailable(isChroma(pu.chType) ? cu : lumaCU, toChannelType(area.compID), area.topRightComp(area.compID), aboveRightUnits, iUnitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + iAboveUnits + 1));
Pel* pDst = nullptr;
Pel const* piSrc = nullptr;
bool isFirstRowOfCtu = (lumaArea.y & ((pu.cs->sps)->getCTUSize() - 1)) == 0;
//获取上侧参考的亮度值
if (aboveIsAvailable)
pDst = pDst0 - iDstStride;
int addedAboveRight = 0;
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
addedAboveRight = avaiAboveRightUnits*chromaUnitWidth;
for (int i = 0; i < uiCWidth + addedAboveRight; i++)
const bool leftPadding = i == 0 && !leftIsAvailable;
if (pu.chromaFormat == CHROMA_444)
piSrc = pRecSrc0 - iRecStride;
pDst[i] = piSrc[i];
else if (isFirstRowOfCtu)
piSrc = pRecSrc0 - iRecStride;
pDst[i] = (piSrc[2 * i] * 2 + piSrc[2 * i - (leftPadding ? 0 : 1)] + piSrc[2 * i + 1] + 2) >> 2;
else if (pu.chromaFormat == CHROMA_422)
piSrc = pRecSrc0 - iRecStride2;
int s = 2;
s += piSrc[2 * i] * 2;
s += piSrc[2 * i - (leftPadding ? 0 : 1)];
s += piSrc[2 * i + 1];
pDst[i] = s >> 2;
else if (pu.cs->sps->getCclmCollocatedChromaFlag())
piSrc = pRecSrc0 - iRecStride2;
int s = 4;
s += piSrc[2 * i - iRecStride];
s += piSrc[2 * i] * 4;
s += piSrc[2 * i - (leftPadding ? 0 : 1)];
s += piSrc[2 * i + 1];
s += piSrc[2 * i + iRecStride];
pDst[i] = s >> 3;
else//420
//色度对于处的6点,平均加权,得到最后的亮度
//piSrc 指向当前块的第一个点的上方2排的点,因为获取下采样的亮度需要两排3个(共6个点)
piSrc = pRecSrc0 - iRecStride2;
int s = 4;
s += piSrc[2 * i] * 2;
s += piSrc[2 * i + 1];
s += piSrc[2 * i - (leftPadding ? 0 : 1)];
s += piSrc[2 * i + iRecStride] * 2;
s += piSrc[2 * i + 1 + iRecStride];
s += piSrc[2 * i + iRecStride - (leftPadding ? 0 : 1)];
pDst[i] = s >> 3;
//获取左侧参考的亮度值
if (leftIsAvailable)
pDst = pDst0 - 1;
//piSrc指向块内第一个点的左边2个点
piSrc = pRecSrc0 - 1 - logSubWidthC;
int addedLeftBelow = 0;
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
addedLeftBelow = avaiLeftBelowUnits*chromaUnitHeight;
for (int j = 0; j < uiCHeight + addedLeftBelow; j++)
if (pu.chromaFormat == CHROMA_444)
pDst[0] = piSrc[0];
else if (pu.chromaFormat == CHROMA_422)
int s = 2;
s += piSrc[0] * 2;
s += piSrc[-1];
s += piSrc[1];
pDst[0] = s >> 2;
else if (pu.cs->sps->getCclmCollocatedChromaFlag())
const bool abovePadding = j == 0 && !aboveIsAvailable;
int s = 4;
s += piSrc[-(abovePadding ? 0 : iRecStride)];
s += piSrc[0] * 4;
s += piSrc[-1];
s += piSrc[1];
s += piSrc[iRecStride];
pDst[0] = s >> 3;
else
int s = 4;
s += piSrc[0] * 2;
s += piSrc[1];
s += piSrc[-1];
s += piSrc[iRecStride] * 2;
s += piSrc[iRecStride + 1];
s += piSrc[iRecStride - 1];
pDst[0] = s >> 3;
piSrc += iRecStride2;
pDst += iDstStride;
// inner part from reconstructed picture buffer
//获取块内部的亮度值
for( int j = 0; j < uiCHeight; j++ )
for( int i = 0; i < uiCWidth; i++ )
if (pu.chromaFormat == CHROMA_444)
pDst0[i] = pRecSrc0[i];
else if (pu.chromaFormat == CHROMA_422)
const bool leftPadding = i == 0 && !leftIsAvailable;
int s = 2;
s += pRecSrc0[2 * i] * 2;
s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
s += pRecSrc0[2 * i + 1];
pDst0[i] = s >> 2;
else if (pu.cs->sps->getCclmCollocatedChromaFlag())
const bool leftPadding = i == 0 && !leftIsAvailable;
const bool abovePadding = j == 0 && !aboveIsAvailable;
int s = 4;
s += pRecSrc0[2 * i - (abovePadding ? 0 : iRecStride)];
s += pRecSrc0[2 * i] * 4;
s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
s += pRecSrc0[2 * i + 1];
s += pRecSrc0[2 * i + iRecStride];
pDst0[i] = s >> 3;
else//420
CHECK(pu.chromaFormat != CHROMA_420, "Chroma format must be 4:2:0 for vertical filtering");
const bool leftPadding = i == 0 && !leftIsAvailable;
int s = 4;
s += pRecSrc0[2 * i] * 2;
s += pRecSrc0[2 * i + 1];
s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
s += pRecSrc0[2 * i + iRecStride] * 2;
s += pRecSrc0[2 * i + 1 + iRecStride];
s += pRecSrc0[2 * i + iRecStride - (leftPadding ? 0 : 1)];
pDst0[i] = s >> 3;
pDst0 += iDstStride;
pRecSrc0 += iRecStride2;
进行CCLM,调用 xGetLMParameters获得a和b的值,然后调用linearTransform将亮度映射到色度上。
void IntraPrediction::predIntraChromaLM(const ComponentID compID, PelBuf &piPred, const PredictionUnit &pu, const CompArea& chromaArea, int intraDir)
int iLumaStride = 0;
PelBuf Temp;
if ((intraDir == MDLM_L_IDX) || (intraDir == MDLM_T_IDX))
iLumaStride = 2 * MAX_CU_SIZE + 1;
Temp = PelBuf(m_pMdlmTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));//获得当前块的第一个像素
else
iLumaStride = MAX_CU_SIZE + 1;
Temp = PelBuf(m_piTemp + iLumaStride + 1, iLumaStride, Size(chromaArea));//获得当前块的第一个像素
//调用xGetLMParameters获取a, b, iShift
int a, b, iShift;
xGetLMParameters(pu, compID, chromaArea, a, b, iShift);
// final prediction
piPred.copyFrom(Temp);//获得当前块的第一个像素
piPred.linearTransform(a, iShift, b, true, pu.cs->slice->clpRng(compID));//通过CCLM的直线对应关系球的当前色度块
void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const ComponentID compID,
const CompArea &chromaArea,
int &a, int &b, int &iShift)
//计算CCLM的参数a,b
CHECK(compID == COMPONENT_Y, "");
const SizeType cWidth = chromaArea.width;
const SizeType cHeight = chromaArea.height;
const Position posLT = chromaArea;
CodingStructure & cs = *(pu.cs);
const CodingUnit &cu = *(pu.cu);
const SPS & sps = *cs.sps;
const uint32_t tuWidth = chromaArea.width;
const uint32_t tuHeight = chromaArea.height;
const ChromaFormat nChromaFormat = sps.getChromaFormatIdc();
const int baseUnitSize = 1 << MIN_CU_LOG2;
const int unitWidth = baseUnitSize >> getComponentScaleX(chromaArea.compID, nChromaFormat);
const int unitHeight = baseUnitSize >> getComponentScaleY(chromaArea.compID, nChromaFormat);
const int tuWidthInUnits = tuWidth / unitWidth;
const int tuHeightInUnits = tuHeight / unitHeight;
const int aboveUnits = tuWidthInUnits;
const int leftUnits = tuHeightInUnits;
int topTemplateSampNum = 2 * cWidth; // for MDLM, the template sample number is 2W or 2H;
int leftTemplateSampNum = 2 * cHeight;
assert(m_topRefLength >= topTemplateSampNum);
assert(m_leftRefLength >= leftTemplateSampNum);
int totalAboveUnits = (topTemplateSampNum + (unitWidth - 1)) / unitWidth;
int totalLeftUnits = (leftTemplateSampNum + (unitHeight - 1)) / unitHeight;
int totalUnits = totalLeftUnits + totalAboveUnits + 1;
int aboveRightUnits = totalAboveUnits - aboveUnits;
int leftBelowUnits = totalLeftUnits - leftUnits;
int avaiAboveRightUnits = 0;
int avaiLeftBelowUnits = 0;
int avaiAboveUnits = 0;
int avaiLeftUnits = 0;
int curChromaMode = pu.intraDir[1];
bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];
memset(neighborFlags, 0, totalUnits);
bool aboveAvailable, leftAvailable;
int availableUnit =
isAboveAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, aboveUnits, unitWidth,
(neighborFlags + leftUnits + leftBelowUnits + 1));
aboveAvailable = availableUnit == tuWidthInUnits;
availableUnit =
isLeftAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, leftUnits, unitHeight,
(neighborFlags + leftUnits + leftBelowUnits - 1));
leftAvailable = availableUnit == tuHeightInUnits;
if (leftAvailable) // if left is not availcurChromaModeable, then the below left is not available
avaiLeftUnits = tuHeightInUnits;
avaiLeftBelowUnits = isBelowLeftAvailable(cu, CHANNEL_TYPE_CHROMA, chromaArea.bottomLeftComp(chromaArea.compID), leftBelowUnits, unitHeight, (neighborFlags + leftBelowUnits - 1));
if (aboveAvailable) // if above is not available, then the above right is not available.
avaiAboveUnits = tuWidthInUnits;
avaiAboveRightUnits = isAboveRightAvailable(cu, CHANNEL_TYPE_CHROMA, chromaArea.topRightComp(chromaArea.compID), aboveRightUnits, unitWidth, (neighborFlags + leftUnits + leftBelowUnits + aboveUnits + 1));
Pel *srcColor0, *curChroma0;
int srcStride;
PelBuf temp;
if ((curChromaMode == MDLM_L_IDX) || ( == MDLM_T_IDX))
srcStride = 2 * MAX_CU_SIZE + 1;
temp = PelBuf(m_pMdlmTemp + srcStride + 1, srcStride, Size(chromaArea));
else
srcStride = MAX_CU_SIZE + 1;
temp = PelBuf(m_piTemp + srcStride + 1, srcStride, Size(chromaArea));
srcColor0 = temp.bufAt(0, 0);
curChroma0 = getPredictorPtr(compID);
unsigned internalBitDepth = sps.getBitDepth(CHANNEL_TYPE_CHROMA);
int minLuma[2] = MAX_INT, 0 ;
int maxLuma[2] = -MAX_INT, 0 ;
Pel *src = srcColor0 - srcStride;
int actualTopTemplateSampNum = 0;
int actualLeftTemplateSampNum = 0;
if (curChromaMode == MDLM_T_IDX)
leftAvailable = 0;
avaiAboveRightUnits = avaiAboveRightUnits > (cHeight/unitWidth) ? cHeight/unitWidth : avaiAboveRightUnits;
actualTopTemplateSampNum = unitWidth*(avaiAboveUnits + avaiAboveRightUnits);
else if (curChromaMode == MDLM_L_IDX)
aboveAvailable = 0;
avaiLeftBelowUnits = avaiLeftBelowUnits > (cWidth/unitHeight) ? cWidth/unitHeight : avaiLeftBelowUnits;
actualLeftTemplateSampNum = unitHeight*(avaiLeftUnits + avaiLeftBelowUnits);
else if (curChromaMode == LM_CHROMA_IDX)
actualTopTemplateSampNum = cWidth;
actualLeftTemplateSampNum = cHeight;
int startPos[2]; //0:Above, 1: Left
int pickStep[2];
int aboveIs4 = leftAvailable ? 0 : 1;//如果左侧可用,那么上侧就不是4个
int leftIs4 = aboveAvailable ? 0 : 1;//如果上侧可用,那么左侧就不是4个
startPos[0] = actualTopTemplateSampNum >> (2 + aboveIs4);//第一个点在参考像素的位置
pickStep[0] = std::max(1, actualTopTemplateSampNum >> (1 + aboveIs4));//选取的点的间隔
startPos[1] = actualLeftTemplateSampNum >> (2 + leftIs4);
pickStep[1] = std::max(1, actualLeftTemplateSampNum >> (1 + leftIs4));
Pel selectLumaPix[4] = 0, 0, 0, 0 ;
Pel selectChromaPix[4] = 0, 0, 0, 0 ;
int cntT, cntL;
cntT = cntL = 0;
int cnt = 0;
if (aboveAvailable)
//如果上侧可用,看他的上侧是不是需要4个点aboveIs4,否则只需要2个
cntT = std::min(actualTopTemplateSampNum, (1 + aboveIs4) << 1);
src = srcColor0 - srcStride;
const Pel *cur = curChroma0 + 1;
for (int pos = startPos[0]; cnt < cntT; pos += pickStep[0], cnt++)
selectLumaPix[cnt] = src[pos];
selectChromaPix[cnt] = cur[pos];
if (leftAvailable)
//如果左侧可用,看他的是不是需要4个点leftIs4,否则只需要2个
cntL = std::min(actualLeftTemplateSampNum, ( 1 + leftIs4 ) << 1 );
src = srcColor0 - 1;
const Pel *cur = curChroma0 + m_refBufferStride[compID] + 1;
for (int pos = startPos[1], cnt = 0; cnt < cntL; pos += pickStep[1], cnt++)
selectLumaPix[cnt + cntT] = src[pos * srcStride];
selectChromaPix[cnt + cntT] = cur[pos];
cnt = cntL + cntT;//正常情况一共是4个,cnt =4
if (cnt == 2)
//如果点数正常,应该是4个点,但是这里只有2个点,表示那么就用0和1给0,1,2,3赋值变成4个点
selectLumaPix[3] = selectLumaPix[0]; selectChromaPix[3] = selectChromaPix[0];
selectLumaPix[2] = selectLumaPix[1]; selectChromaPix[2] = selectChromaPix[1];
selectLumaPix[0] = selectLumaPix[1]; selectChromaPix[0] = selectChromaPix[1];
selectLumaPix[1] = selectLumaPix[3]; selectChromaPix[1] = selectChromaPix[3];
//先假定较小的是0和2,较大的是1,3
int minGrpIdx[2] = 0, 2 ;
int maxGrpIdx[2] = 1, 3 ;
int *tmpMinGrp = minGrpIdx;
int *tmpMaxGrp = maxGrpIdx;
if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMinGrp[1]])
//如果0比2大,则交换0和2. 就是把小的放在前面
std::swap(tmpMinGrp[0], tmpMinGrp[1]);
if (selectLumaPix[tmpMaxGrp[0]] > selectLumaPix[tmpMaxGrp[1]])
//如果1比3大则交换, 小的放前面
std::swap(tmpMaxGrp[0], tmpMaxGrp[1]);
if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMaxGrp[1]])
//如果tmpMinGrp[0]比tmpMaxGrp[1]中的数据大,则交换tmpMinGrp和tmpMaxGrp
//(这里不能使用0,1,2,3代替,因为可能在上面的if中换了顺序)
std::swap(tmpMinGrp, tmpMaxGrp);
if (selectLumaPix[tmpMinGrp[1]] > selectLumaPix[tmpMaxGrp[0]])
//如果tmpMinGrp[1]中的数据比tmpMaxGrp[0]大,则交换。
std::swap(tmpMinGrp[1], tmpMaxGrp[0]);
//这一段做完后tmpMinGrp中放的就是亮度值较小的2个序号,tmpMaxGrp中放的是较大的两个序号
//(tmpMinGrp/tmpMaxGrp里面的大小不用管,反正要求的是平均值)
//分为亮度较大的两个样本和亮度较小的两组样本,求这两个点的亮度色度平均值
minLuma[0] = (selectLumaPix[tmpMinGrp[0]] + selectLumaPix[tmpMinGrp[1]] + 1 )>>1;
minLuma[1] = (selectChromaPix[tmpMinGrp[0]] + selectChromaPix[tmpMinGrp[1]] + 1) >> 1; //minLuma是色度!
maxLuma[0] = (selectLumaPix[tmpMaxGrp[0]] + selectLumaPix[tmpMaxGrp[1]] + 1 )>>1;
maxLuma[1] = (selectChromaPix[tmpMaxGrp[0]] + selectChromaPix[tmpMaxGrp[1]] + 1) >> 1; //maxLuma是色度!
if (leftAvailable || aboveAvailable)
//如果上方或者左侧的参考像素可用
int diff = maxLuma[0] - minLuma[0];
if (diff > 0)
//
int diffC = maxLuma[1] - minLuma[1];
int x = floorLog2( diff );
static const uint8_t DivSigTable[1 << 4] =
// 4bit significands - 8 ( MSB is omitted )
0, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 0
;
int normDiff = (diff << 4 >> x) & 15;
int v = DivSigTable[normDiff] | 8;
x += normDiff != 0;
int y = floorLog2( abs( diffC ) ) + 1;
int add = 1 << y >> 1;
a = (diffC * v + add) >> y;
iShift = 3 + x - y;
if ( iShift < 1 )
iShift = 1;
a = ( (a == 0)? 0: (a < 0)? -15 : 15 ); // a=Sign(a)*15
b = minLuma[1] - ((a * minLuma[0]) >> iShift);
else//如果maxLuma[0] - minLuma[0]=0,(应该不会出现小于0 的情况吧??)
//那么a=0,b=minLuma[1](亮度较小的两个像素的色度平均值)
a = 0;
b = minLuma[1];
iShift = 0;
else//如果上和左的参考像素都不能用
//那么a=0,b为固定值
a = 0;
b = 1 << (internalBitDepth - 1);
iShift = 0;
以上是关于VTM10.0帧内之CCLM技术的主要内容,如果未能解决你的问题,请参考以下文章