Void printBlockToStream( std::ostream &ss, const Char *pLinePrefix, TComYuv &src, const UInt numSubBlocksAcross, const UInt numSubBlocksUp, const UInt defWidth ) { const UInt numValidComp=src.getNumberValidComponents(); for (UInt ch=0; ch<numValidComp ; ch++) { const ComponentID compID = ComponentID(ch); const UInt width = src.getWidth(compID); const UInt height = src.getHeight(compID); const UInt stride = src.getStride(compID); const Pel* blkSrc = src.getAddr(compID); const UInt subBlockWidth=width/numSubBlocksAcross; const UInt subBlockHeight=height/numSubBlocksUp; ss << pLinePrefix << " compID: " << compID << "\n"; for (UInt y=0; y<height; y++) { if ((y%subBlockHeight)==0 && y!=0) ss << pLinePrefix << '\n'; ss << pLinePrefix; for (UInt x=0; x<width; x++) { if ((x%subBlockWidth)==0 && x!=0) ss << std::setw(defWidth+2) << ""; ss << std::setw(defWidth) << blkSrc[y*stride + x] << ' '; } ss << '\n'; } ss << pLinePrefix << " --- \n"; } }
//! calculate AC and DC values for current original image Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice) { //===== calculate AC/DC value ===== TComPicYuv* pPic = slice->getPic()->getPicYuvOrg(); WPACDCParam weightACDCParam[MAX_NUM_COMPONENT]; for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) { const ComponentID compID = ComponentID(componentIndex); // calculate DC/AC value for channel const Int iStride = pPic->getStride(compID); const Int iWidth = pPic->getWidth(compID); const Int iHeight = pPic->getHeight(compID); const Int iSample = iWidth*iHeight; Int64 iOrgDC = 0; { const Pel *pPel = pPic->getAddr(compID); for(Int y = 0; y < iHeight; y++, pPel+=iStride ) { for(Int x = 0; x < iWidth; x++ ) { iOrgDC += (Int)( pPel[x] ); } } } const Int64 iOrgNormDC = ((iOrgDC+(iSample>>1)) / iSample); Int64 iOrgAC = 0; { const Pel *pPel = pPic->getAddr(compID); for(Int y = 0; y < iHeight; y++, pPel += iStride ) { for(Int x = 0; x < iWidth; x++ ) { iOrgAC += abs( (Int)pPel[x] - (Int)iOrgNormDC ); } } } const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0; weightACDCParam[compID].iDC = (((iOrgDC<<fixedBitShift)+(iSample>>1)) / iSample); weightACDCParam[compID].iAC = iOrgAC; } slice->setWpAcDcParam(weightACDCParam); }
Void printCbfArray( TComDataCU* pcCU ) { const UInt CUSizeInParts = pcCU->getWidth(0)/4; const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); for (UInt ch=0; ch<numValidComp; ch++) { const ComponentID compID=ComponentID(ch); printf("channel: %d\n", ch); for (Int y=0; y<CUSizeInParts; y++) { for (Int x=0; x<CUSizeInParts; x++) { printf(x+1==CUSizeInParts?"%3d\n":"%3d, ", pcCU->getCbf(compID)[g_auiRasterToZscan[y*CUSizeInParts + x]]); } } } }
ResultCircuits Tesseract::TesseractCircuits(Rectangle rect) { ResultCircuits result; // Set the region of interest and copy the image in memory. cvSetImageROI(m_gray, cvRect(rect.GetX(), rect.GetY(), rect.GetWidth(),rect.GetHeight())); IplImage* roi = cvCreateImage(cvGetSize(m_gray), m_gray->depth, 1); cvCopy(m_gray, roi); // Reset the region of interest. cvResetImageROI(m_gray); // Now, process the copied image, roi. tesseract::TessBaseAPI api; api.Init(".", "cir"); api.SetVariable("save_best_choices", "T"); api.SetPageSegMode(tesseract::PSM_SINGLE_CHAR); api.SetImage((uint8_t*) roi->imageData, roi->width, roi->height, 1, roi->widthStep); result.m_confidence = api.MeanTextConf(); char* utf8 = api.GetUTF8Text(); std::string chars = std::string(utf8); delete[] utf8; chars.erase(std::remove_if(chars.begin(), chars.end(), iswhitespace), chars.end()); for (unsigned int i = 0; i < chars.length(); i++) { result.m_vector.push_back(ComponentID(chars[i])); } // Cleanup and return. cvReleaseImage(&roi); return result; }
Void TEncEntropy::xEncodeTransform( Bool& bCodeDQP, Bool& codeChromaQpAdj, TComTU &rTu ) { //pcCU, absPartIdxCU, uiAbsPartIdx, uiDepth+1, uiTrIdx+1, quadrant, TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const UInt numValidComponent = pcCU->getPic()->getNumberValidComponents(); const Bool bChroma = isChromaEnabled(pcCU->getPic()->getChromaFormat()); const UInt uiTrIdx = rTu.GetTransformDepthRel(); const UInt uiDepth = rTu.GetTransformDepthTotal(); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST const Bool bDebugRQT=pcCU->getSlice()->getFinalized() && DebugOptionList::DebugRQT.getInt()!=0; if (bDebugRQT) { printf("x..codeTransform: offsetLuma=%d offsetChroma=%d absPartIdx=%d, uiDepth=%d\n width=%d, height=%d, uiTrIdx=%d, uiInnerQuadIdx=%d\n", rTu.getCoefficientOffset(COMPONENT_Y), rTu.getCoefficientOffset(COMPONENT_Cb), uiAbsPartIdx, uiDepth, rTu.getRect(COMPONENT_Y).width, rTu.getRect(COMPONENT_Y).height, rTu.GetTransformDepthRel(), rTu.GetSectionNumber()); } #endif const UInt uiSubdiv = pcCU->getTransformIdx( uiAbsPartIdx ) > uiTrIdx;// + pcCU->getDepth( uiAbsPartIdx ) > uiDepth; const UInt uiLog2TrafoSize = rTu.GetLog2LumaTrSize(); UInt cbf[MAX_NUM_COMPONENT] = {0,0,0}; Bool bHaveACodedBlock = false; Bool bHaveACodedChromaBlock = false; for(UInt ch=0; ch<numValidComponent; ch++) { const ComponentID compID = ComponentID(ch); cbf[compID] = pcCU->getCbf( uiAbsPartIdx, compID , uiTrIdx ); if (cbf[ch] != 0) { bHaveACodedBlock = true; if (isChroma(compID)) { bHaveACodedChromaBlock = true; } } } if( pcCU->isIntra(uiAbsPartIdx) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_NxN && uiDepth == pcCU->getDepth(uiAbsPartIdx) ) { assert( uiSubdiv ); } else if( pcCU->isInter(uiAbsPartIdx) && (pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N) && uiDepth == pcCU->getDepth(uiAbsPartIdx) && (pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) ) { if ( uiLog2TrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( uiSubdiv ); } else { assert(!uiSubdiv ); } } else if( uiLog2TrafoSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { assert( uiSubdiv ); } else if( uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { assert( !uiSubdiv ); } else if( uiLog2TrafoSize == pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( !uiSubdiv ); } else { assert( uiLog2TrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSubdiv, 5 - uiLog2TrafoSize ); } const UInt uiTrDepthCurr = uiDepth - pcCU->getDepth( uiAbsPartIdx ); const Bool bFirstCbfOfCU = uiTrDepthCurr == 0; for(UInt ch=COMPONENT_Cb; ch<numValidComponent; ch++) { const ComponentID compID=ComponentID(ch); if( bFirstCbfOfCU || rTu.ProcessingAllQuadrants(compID) ) { if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepthCurr - 1 ) ) { m_pcEntropyCoderIf->codeQtCbf( rTu, compID, (uiSubdiv == 0) ); } } else { assert( pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepthCurr ) == pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepthCurr - 1 ) ); } } if( uiSubdiv ) { TComTURecurse tuRecurseChild(rTu, true); do { xEncodeTransform( bCodeDQP, codeChromaQpAdj, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } else { { DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tTrIdx: abspart=" ); DTRACE_CABAC_V( uiAbsPartIdx ); DTRACE_CABAC_T( "\tdepth=" ); DTRACE_CABAC_V( uiDepth ); DTRACE_CABAC_T( "\ttrdepth=" ); DTRACE_CABAC_V( pcCU->getTransformIdx( uiAbsPartIdx ) ); DTRACE_CABAC_T( "\n" ); } if( !pcCU->isIntra(uiAbsPartIdx) && uiDepth == pcCU->getDepth( uiAbsPartIdx ) && (!bChroma || (!pcCU->getCbf( uiAbsPartIdx, COMPONENT_Cb, 0 ) && !pcCU->getCbf( uiAbsPartIdx, COMPONENT_Cr, 0 ) ) ) ) { assert( pcCU->getCbf( uiAbsPartIdx, COMPONENT_Y, 0 ) ); // printf( "saved one bin! " ); } else { m_pcEntropyCoderIf->codeQtCbf( rTu, COMPONENT_Y, true ); //luma CBF is always at the lowest level } if ( bHaveACodedBlock ) { // dQP: only for CTU once if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { if ( bCodeDQP ) { encodeQP( pcCU, rTu.GetAbsPartIdxCU() ); bCodeDQP = false; } } if ( pcCU->getSlice()->getUseChromaQpAdj() ) { if ( bHaveACodedChromaBlock && codeChromaQpAdj && !pcCU->getCUTransquantBypass(rTu.GetAbsPartIdxCU()) ) { encodeChromaQpAdjustment( pcCU, rTu.GetAbsPartIdxCU() ); codeChromaQpAdj = false; } } const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++) { const ComponentID compID=ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("Call NxN for chan %d width=%d height=%d cbf=%d\n", compID, rTu.getRect(compID).width, rTu.getRect(compID).height, 1); } #endif if (rTu.getRect(compID).width != rTu.getRect(compID).height) { //code two sub-TUs TComTURecurse subTUIterator(rTu, false, TComTU::VERTICAL_SPLIT, true, compID); do { const UChar subTUCBF = pcCU->getCbf(subTUIterator.GetAbsPartIdxTU(compID), compID, (uiTrIdx + 1)); if (subTUCBF != 0) { #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("Call NxN for chan %d width=%d height=%d cbf=%d\n", compID, subTUIterator.getRect(compID).width, subTUIterator.getRect(compID).height, 1); } #endif m_pcEntropyCoderIf->codeCoeffNxN( subTUIterator, (pcCU->getCoeff(compID) + subTUIterator.getCoefficientOffset(compID)), compID ); } } while (subTUIterator.nextSection(rTu)); } else { if (isChroma(compID) && (cbf[COMPONENT_Y] != 0)) { m_pcEntropyCoderIf->codeCrossComponentPrediction( rTu, compID ); } if (cbf[compID] != 0) { m_pcEntropyCoderIf->codeCoeffNxN( rTu, (pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID)), compID ); } } } } } } }
//! 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 TEncTop::encode(Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded, Bool isTff) { iNumEncoded = 0; for (Int fieldNum=0; fieldNum<2; fieldNum++) { if (pcPicYuvOrg) { /* -- field initialization -- */ const Bool isTopField=isTff==(fieldNum==0); TComPic *pcField; xGetNewPicBuffer( pcField ); pcField->setReconMark (false); // where is this normally? if (fieldNum==1) // where is this normally? { TComPicYuv* rpcPicYuvRec; // org. buffer if ( rcListPicYuvRecOut.size() >= (UInt)m_iGOPSize+1 ) // need to maintain field 0 in list of RecOuts while processing field 1. Hence +1 on m_iGOPSize. { rpcPicYuvRec = rcListPicYuvRecOut.popFront(); } else { rpcPicYuvRec = new TComPicYuv; rpcPicYuvRec->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, true); } rcListPicYuvRecOut.pushBack( rpcPicYuvRec ); } pcField->getSlice(0)->setPOC( m_iPOCLast ); // superfluous? pcField->getPicYuvRec()->setBorderExtension(false);// where is this normally? pcField->setTopField(isTopField); // interlaced requirement for (UInt componentIndex = 0; componentIndex < pcPicYuvOrg->getNumberValidComponents(); componentIndex++) { const ComponentID component = ComponentID(componentIndex); const UInt stride = pcPicYuvOrg->getStride(component); separateFields((pcPicYuvOrg->getBuf(component) + pcPicYuvOrg->getMarginX(component) + (pcPicYuvOrg->getMarginY(component) * stride)), pcField->getPicYuvOrg()->getAddr(component), pcPicYuvOrg->getStride(component), pcPicYuvOrg->getWidth(component), pcPicYuvOrg->getHeight(component), isTopField); separateFields((pcPicYuvTrueOrg->getBuf(component) + pcPicYuvTrueOrg->getMarginX(component) + (pcPicYuvTrueOrg->getMarginY(component) * stride)), pcField->getPicYuvTrueOrg()->getAddr(component), pcPicYuvTrueOrg->getStride(component), pcPicYuvTrueOrg->getWidth(component), pcPicYuvTrueOrg->getHeight(component), isTopField); } // compute image characteristics if ( getUseAdaptiveQP() ) { m_cPreanalyzer.xPreanalyze( dynamic_cast<TEncPic*>( pcField ) ); } } if ( m_iNumPicRcvd && ((flush&&fieldNum==1) || (m_iPOCLast/2)==0 || m_iNumPicRcvd==m_iGOPSize ) ) { // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, true, isTff, snrCSC, m_printFrameMSE,&m_cSearch); iNumEncoded += m_iNumPicRcvd; m_uiNumAllPicCoded += m_iNumPicRcvd; m_iNumPicRcvd = 0; } } }
//! 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; } } }