/** * \brief Filter a block of Luma/Chroma samples (vertical) * * \param compID Colour component ID * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param frac Fractional sample offset * \param isFirst Flag indicating whether it is the first filtering operation * \param isLast Flag indicating whether it is the last filtering operation * \param fmt Chroma format */ Void TComInterpolationFilter::filterVer(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isFirst, Bool isLast, const ChromaFormat fmt ) { if ( frac == 0 ) { filterCopy(g_bitDepth[toChannelType(compID)], src, srcStride, dst, dstStride, width, height, isFirst, isLast ); } else if (isLuma(compID)) { assert(frac >= 0 && frac < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterVer<NTAPS_LUMA>(g_bitDepth[toChannelType(compID)], src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaFilter[frac]); } else { const UInt csy = getComponentScaleY(compID, fmt); assert(frac >=0 && csy<2 && (frac<<(1-csy)) < CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterVer<NTAPS_CHROMA>(g_bitDepth[toChannelType(compID)], src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_chromaFilter[frac<<(1-csy)]); } }
//! weighted averaging for bi-pred Void TComWeightPrediction::addWeightBi( const TComYuv *pcYuvSrc0, const TComYuv *pcYuvSrc1, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, const WPScalingParam *const wp1, TComYuv *const rpcYuvDst, const Bool bRoundLuma) { const Bool enableRounding[MAX_NUM_COMPONENT]={ bRoundLuma, true, true }; const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents(); for(Int componentIndex=0; componentIndex<numValidComponent; componentIndex++) { const ComponentID compID=ComponentID(componentIndex); const Pel* pSrc0 = pcYuvSrc0->getAddr( compID, iPartUnitIdx ); const Pel* pSrc1 = pcYuvSrc1->getAddr( compID, iPartUnitIdx ); Pel* pDst = rpcYuvDst->getAddr( compID, iPartUnitIdx ); // Luma : -------------------------------------------- const Int w0 = wp0[compID].w; const Int offset = wp0[compID].offset; const Int clipBD = bitDepths.recon[toChannelType(compID)]; const Int shiftNum = std::max<Int>(2, (IF_INTERNAL_PREC - clipBD)); const Int shift = wp0[compID].shift + shiftNum; const Int round = (enableRounding[compID] && (shift > 0)) ? (1<<(shift-1)) : 0; const Int w1 = wp1[compID].w; const UInt csx = pcYuvSrc0->getComponentScaleX(compID); const UInt csy = pcYuvSrc0->getComponentScaleY(compID); const Int iHeight = uiHeight>>csy; const Int iWidth = uiWidth>>csx; const UInt iSrc0Stride = pcYuvSrc0->getStride(compID); const UInt iSrc1Stride = pcYuvSrc1->getStride(compID); const UInt iDstStride = rpcYuvDst->getStride(compID); for ( Int y = iHeight-1; y >= 0; y-- ) { // do it in batches of 4 (partial unroll) Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; } for( ; x >= 0; x-- ) { pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); } pSrc0 += iSrc0Stride; pSrc1 += iSrc1Stride; pDst += iDstStride; } // y loop } // compID loop }
//======================================================= // getWpScaling() //======================================================= //! derivation of wp tables Void TComWeightPrediction::getWpScaling( TComDataCU *const pcCU, const Int iRefIdx0, const Int iRefIdx1, WPScalingParam *&wp0, WPScalingParam *&wp1) { assert(iRefIdx0 >= 0 || iRefIdx1 >= 0); TComSlice *const pcSlice = pcCU->getSlice(); const Bool wpBiPred = pcCU->getSlice()->getPPS()->getWPBiPred(); const Bool bBiPred = (iRefIdx0>=0 && iRefIdx1>=0); const Bool bUniPred = !bBiPred; if ( bUniPred || wpBiPred ) { // explicit -------------------- if ( iRefIdx0 >= 0 ) { pcSlice->getWpScaling(REF_PIC_LIST_0, iRefIdx0, wp0); } if ( iRefIdx1 >= 0 ) { pcSlice->getWpScaling(REF_PIC_LIST_1, iRefIdx1, wp1); } } else { assert(0); } if ( iRefIdx0 < 0 ) { wp0 = NULL; } if ( iRefIdx1 < 0 ) { wp1 = NULL; } const UInt numValidComponent = pcCU->getPic()->getNumberValidComponents(); const Bool bUseHighPrecisionPredictionWeighting = pcSlice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); if ( bBiPred ) { // Bi-predictive case for ( Int yuv=0 ; yuv<numValidComponent ; yuv++ ) { const Int bitDepth = pcSlice->getSPS()->getBitDepth(toChannelType(ComponentID(yuv))); const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8)); wp0[yuv].w = wp0[yuv].iWeight; wp1[yuv].w = wp1[yuv].iWeight; wp0[yuv].o = wp0[yuv].iOffset * offsetScalingFactor; wp1[yuv].o = wp1[yuv].iOffset * offsetScalingFactor; wp0[yuv].offset = wp0[yuv].o + wp1[yuv].o; wp0[yuv].shift = wp0[yuv].uiLog2WeightDenom + 1; wp0[yuv].round = (1 << wp0[yuv].uiLog2WeightDenom); wp1[yuv].offset = wp0[yuv].offset; wp1[yuv].shift = wp0[yuv].shift; wp1[yuv].round = wp0[yuv].round; } } else { // UniPred WPScalingParam *const pwp = (iRefIdx0>=0) ? wp0 : wp1 ; for ( Int yuv=0 ; yuv<numValidComponent ; yuv++ ) { const Int bitDepth = pcSlice->getSPS()->getBitDepth(toChannelType(ComponentID(yuv))); const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8)); pwp[yuv].w = pwp[yuv].iWeight; pwp[yuv].offset = pwp[yuv].iOffset * offsetScalingFactor; pwp[yuv].shift = pwp[yuv].uiLog2WeightDenom; pwp[yuv].round = (pwp[yuv].uiLog2WeightDenom>=1) ? (1 << (pwp[yuv].uiLog2WeightDenom-1)) : (0); } } }
//! weighted averaging for uni-pred Void TComWeightPrediction::addWeightUni( const TComYuv *const pcYuvSrc0, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, TComYuv *const pcYuvDst ) { const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents(); for(Int componentIndex=0; componentIndex<numValidComponent; componentIndex++) { const ComponentID compID=ComponentID(componentIndex); const Pel* pSrc0 = pcYuvSrc0->getAddr( compID, iPartUnitIdx ); Pel* pDst = pcYuvDst->getAddr( compID, iPartUnitIdx ); // Luma : -------------------------------------------- const Int w0 = wp0[compID].w; const Int offset = wp0[compID].offset; const Int clipBD = bitDepths.recon[toChannelType(compID)]; const Int shiftNum = std::max<Int>(2, (IF_INTERNAL_PREC - clipBD)); const Int shift = wp0[compID].shift + shiftNum; const UInt iSrc0Stride = pcYuvSrc0->getStride(compID); const UInt iDstStride = pcYuvDst->getStride(compID); const UInt csx = pcYuvSrc0->getComponentScaleX(compID); const UInt csy = pcYuvSrc0->getComponentScaleY(compID); const Int iHeight = uiHeight>>csy; const Int iWidth = uiWidth>>csx; if (w0 != 1 << wp0[compID].shift) { const Int round = (shift > 0) ? (1<<(shift-1)) : 0; for (Int y = iHeight-1; y >= 0; y-- ) { Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; } for( ; x >= 0; x--) { pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); } pSrc0 += iSrc0Stride; pDst += iDstStride; } } else { const Int round = (shiftNum > 0) ? (1<<(shiftNum-1)) : 0; if (offset == 0) { for (Int y = iHeight-1; y >= 0; y-- ) { Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; } for( ; x >= 0; x--) { pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); } pSrc0 += iSrc0Stride; pDst += iDstStride; } } else { for (Int y = iHeight-1; y >= 0; y-- ) { Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; } for( ; x >= 0; x--) { pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); } pSrc0 += iSrc0Stride; pDst += iDstStride; } } } } }
Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic* pcPic, TDecSbac* pcSbacDecoder) { TComSlice* pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx()); const Int startCtuTsAddr = pcSlice->getSliceSegmentCurStartCtuTsAddr(); const Int startCtuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTsAddr); const UInt numCtusInFrame = pcPic->getNumberOfCtusInFrame(); const UInt frameWidthInCtus = pcPic->getPicSym()->getFrameWidthInCtus(); const Bool depSliceSegmentsEnabled = pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag(); const Bool wavefrontsEnabled = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag(); m_pcEntropyDecoder->setEntropyDecoder ( pcSbacDecoder ); m_pcEntropyDecoder->setBitstream ( ppcSubstreams[0] ); m_pcEntropyDecoder->resetEntropy (pcSlice); // decoder doesn't need prediction & residual frame buffer pcPic->setPicYuvPred( 0 ); pcPic->setPicYuvResi( 0 ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( pcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif // The first CTU of the slice is the first coded substream, but the global substream number, as calculated by getSubstreamForCtuAddr may be higher. // This calculates the common offset for all substreams in this slice. const UInt subStreamOffset=pcPic->getSubstreamForCtuAddr(startCtuRsAddr, true, pcSlice); if (depSliceSegmentsEnabled) { // modify initial contexts with previous slice segment if this is a dependent slice. const UInt startTileIdx=pcPic->getPicSym()->getTileIdxMap(startCtuRsAddr); const TComTile *pCurrentTile=pcPic->getPicSym()->getTComTile(startTileIdx); const UInt firstCtuRsAddrOfTile = pCurrentTile->getFirstCtuRsAddr(); if( pcSlice->getDependentSliceSegmentFlag() && startCtuRsAddr != firstCtuRsAddrOfTile) { if ( pCurrentTile->getTileWidthInCtus() >= 2 || !wavefrontsEnabled) { pcSbacDecoder->loadContexts(&m_lastSliceSegmentEndContextState); } } } // for every CTU in the slice segment... Bool isLastCtuOfSliceSegment = false; for( UInt ctuTsAddr = startCtuTsAddr; !isLastCtuOfSliceSegment && ctuTsAddr < numCtusInFrame; ctuTsAddr++) { const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr); const TComTile ¤tTile = *(pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr))); const UInt firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr(); const UInt tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus; const UInt tileYPosInCtus = firstCtuRsAddrOfTile / frameWidthInCtus; const UInt ctuXPosInCtus = ctuRsAddr % frameWidthInCtus; const UInt ctuYPosInCtus = ctuRsAddr / frameWidthInCtus; const UInt uiSubStrm=pcPic->getSubstreamForCtuAddr(ctuRsAddr, true, pcSlice)-subStreamOffset; TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); pCtu->initCtu( pcPic, ctuRsAddr ); m_pcEntropyDecoder->setBitstream( ppcSubstreams[uiSubStrm] ); // set up CABAC contexts' state for this CTU if (ctuRsAddr == firstCtuRsAddrOfTile) { if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset { m_pcEntropyDecoder->resetEntropy(pcSlice); } } else if (ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled) { // Synchronize cabac probabilities with upper-right CTU if it's available and at the start of a line. if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset { m_pcEntropyDecoder->resetEntropy(pcSlice); } TComDataCU *pCtuUp = pCtu->getCtuAbove(); if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus) ) { TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 ); if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) ) { // Top-right is available, so use it. pcSbacDecoder->loadContexts( &m_entropyCodingSyncContextState ); } } } #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif if ( pcSlice->getSPS()->getUseSAO() ) { SAOBlkParam& saoblkParam = (pcPic->getPicSym()->getSAOBlkParam())[ctuRsAddr]; Bool bIsSAOSliceEnabled = false; Bool sliceEnabled[MAX_NUM_COMPONENT]; for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++) { ComponentID compId=ComponentID(comp); sliceEnabled[compId] = pcSlice->getSaoEnabledFlag(toChannelType(compId)) && (comp < pcPic->getNumberValidComponents()); if (sliceEnabled[compId]) bIsSAOSliceEnabled=true; saoblkParam[compId].modeIdc = SAO_MODE_OFF; } if (bIsSAOSliceEnabled) { Bool leftMergeAvail = false; Bool aboveMergeAvail= false; //merge left condition Int rx = (ctuRsAddr % frameWidthInCtus); if(rx > 0) { leftMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-1); } //merge up condition Int ry = (ctuRsAddr / frameWidthInCtus); if(ry > 0) { aboveMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-frameWidthInCtus); } #if SVC_EXTENSION pcSbacDecoder->parseSAOBlkParam( saoblkParam, m_saoMaxOffsetQVal, sliceEnabled, leftMergeAvail, aboveMergeAvail); #else pcSbacDecoder->parseSAOBlkParam( saoblkParam, sliceEnabled, leftMergeAvail, aboveMergeAvail); #endif } } m_pcCuDecoder->decodeCtu ( pCtu, isLastCtuOfSliceSegment ); m_pcCuDecoder->decompressCtu ( pCtu ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif //Store probabilities of second CTU in line into buffer if ( ctuXPosInCtus == tileXPosInCtus+1 && wavefrontsEnabled) { m_entropyCodingSyncContextState.loadContexts( pcSbacDecoder ); } // Should the sub-stream/stream be terminated after this CTU? // (end of slice-segment, end of tile, end of wavefront-CTU-row) if (isLastCtuOfSliceSegment || ( ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus() && ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getTileHeightInCtus() || wavefrontsEnabled) ) ) { UInt binVal; pcSbacDecoder->parseTerminatingBit( binVal ); assert( binVal ); #if DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES pcSbacDecoder->parseRemainingBytes(!isLastCtuOfSliceSegment); #endif if (isLastCtuOfSliceSegment) { if(!pcSlice->getDependentSliceSegmentFlag()) { pcSlice->setSliceCurEndCtuTsAddr( ctuTsAddr+1 ); } pcSlice->setSliceSegmentCurEndCtuTsAddr( ctuTsAddr+1 ); break; } } } assert(isLastCtuOfSliceSegment == true); if( depSliceSegmentsEnabled ) { m_lastSliceSegmentEndContextState.loadContexts( pcSbacDecoder );//ctx end of dep.slice } }
Void getTUEntropyCodingParameters( TUEntropyCodingParameters &result, TComTU &rTu, const ComponentID component) { //------------------------------------------------ //set the local parameters TComDataCU *const pcCU = rTu.getCU(); const TComRectangle & area = rTu.getRect(component); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(component); const UInt log2BlockWidth = g_aucConvertToBit[area.width] + 2; const UInt log2BlockHeight = g_aucConvertToBit[area.height] + 2; const ChannelType channelType = toChannelType(component); result.scanType = COEFF_SCAN_TYPE(pcCU->getCoefScanIdx(uiAbsPartIdx, area.width, area.height, component)); //------------------------------------------------ //set the group layout result.widthInGroups = area.width >> MLS_CG_LOG2_WIDTH; result.heightInGroups = area.height >> MLS_CG_LOG2_HEIGHT; //------------------------------------------------ //set the scan orders const UInt log2WidthInGroups = g_aucConvertToBit[result.widthInGroups * 4]; const UInt log2HeightInGroups = g_aucConvertToBit[result.heightInGroups * 4]; result.scan = g_scanOrder[ SCAN_GROUPED_4x4 ][ result.scanType ][ log2BlockWidth ][ log2BlockHeight ]; result.scanCG = g_scanOrder[ SCAN_UNGROUPED ][ result.scanType ][ log2WidthInGroups ][ log2HeightInGroups ]; //------------------------------------------------ //set the significance map context selection parameters if (pcCU->getSlice()->getSPS()->getUseSingleSignificanceMapContext() && (pcCU->getCUTransquantBypass(uiAbsPartIdx) || (pcCU->getTransformSkip(uiAbsPartIdx, component) != 0))) { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_SINGLE]; } else { if ((area.width == 4) && (area.height == 4)) { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_4x4]; } else if ((area.width == 8) && (area.height == 8)) { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_8x8]; if (result.scanType != SCAN_DIAG) result.firstSignificanceMapContext += nonDiagonalScan8x8ContextOffset[channelType]; } else { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_NxN]; } } //------------------------------------------------ }
//! update wp tables for explicit wp w.r.t range limitation Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom) { const Int numComp = slice->getPic()->getPicYuvOrg()->getNumberValidComponents(); const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); const Int numPredDir = slice->isInterP() ? 1 : 2; assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); for ( Int refList = 0; refList < numPredDir; refList++ ) { const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) { WPACDCParam *currWeightACDCParam, *refWeightACDCParam; slice->getWpAcDcParam(currWeightACDCParam); slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam); for ( Int comp = 0; comp < numComp; comp++ ) { const ComponentID compID = ComponentID(comp); const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); const Int range = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128; const Int realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8)); const Int realOffset = ((Int)1<<(realLog2Denom-1)); // current frame const Int64 currDC = currWeightACDCParam[comp].iDC; const Int64 currAC = currWeightACDCParam[comp].iAC; // reference frame const Int64 refDC = refWeightACDCParam[comp].iDC; const Int64 refAC = refWeightACDCParam[comp].iAC; // calculating iWeight and iOffset params const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) ); const Int weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) ); const Int offset = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom ); Int clippedOffset; if(isChroma(compID)) // Chroma offset range limination { const Int pred = ( range - ( ( range*weight)>>(log2Denom) ) ); const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) ); // signed 8bit } else // Luma offset range limitation { clippedOffset = Clip3( -range, range-1, offset); } // Weighting factor limitation const Int defaultWeight = (1<<log2Denom); const Int deltaWeight = (defaultWeight - weight); if(deltaWeight >= range || deltaWeight < -range) { return false; } m_wp[refList][refIdxTemp][comp].bPresentFlag = true; m_wp[refList][refIdxTemp][comp].iWeight = weight; m_wp[refList][refIdxTemp][comp].iOffset = clippedOffset; m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom; } } }