/** destroy non-deblocked filter information for LCU */ Void TComPic::destroyNonDBFilterInfo() { if(m_pbValidSlice != NULL) { delete[] m_pbValidSlice; m_pbValidSlice = NULL; } if(m_pSliceSUMap != NULL) { delete[] m_pSliceSUMap; m_pSliceSUMap = NULL; } for( UInt CUAddr = 0; CUAddr < getNumCUsInFrame() ; CUAddr++ ) { TComDataCU* pcCU = getCU( CUAddr ); pcCU->getNDBFilterBlocks()->clear(); } if( m_bIndependentSliceBoundaryForNDBFilter || m_bIndependentTileBoundaryForNDBFilter) { m_pNDBFilterYuvTmp->destroy(); delete m_pNDBFilterYuvTmp; m_pNDBFilterYuvTmp = NULL; } }
Void TComPic::compressMotion() { TComPicSym* pPicSym = getPicSym(); for ( UInt uiCUAddr = 0; uiCUAddr < pPicSym->getFrameHeightInCU()*pPicSym->getFrameWidthInCU(); uiCUAddr++ ) { TComDataCU* pcCU = pPicSym->getCU(uiCUAddr); pcCU->compressMV(); } }
Void TComPic::compressMotion() { TComPicSym* pPicSym = getPicSym(); for ( UInt uiCUAddr = 0; uiCUAddr < pPicSym->getNumberOfCtusInFrame(); uiCUAddr++ ) { TComDataCU* pCtu = pPicSym->getCtu(uiCUAddr); pCtu->compressMV(); } }
Void TDecSlice::decompressSlice(TComBitstream* pcBitstream, TComPic*& rpcPic) { TComDataCU* pcCU; UInt uiIsLast = 0; #if QC_MDDT//ADAPTIVE_SCAN InitScanOrderForSlice(); #endif // decoder don't need prediction & residual frame buffer rpcPic->setPicYuvPred( 0 ); rpcPic->setPicYuvResi( 0 ); #if HHI_RQT #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_V( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( rpcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif #endif // for all CUs for( Int iCUAddr = 0; !uiIsLast; iCUAddr++ ) { pcCU = rpcPic->getCU( iCUAddr ); pcCU->initCU( rpcPic, iCUAddr ); #if HHI_RQT #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif #endif m_pcCuDecoder->decodeCU ( pcCU, uiIsLast ); m_pcCuDecoder->decompressCU ( pcCU ); #if QC_MDDT//ADAPTIVE_SCAN updateScanOrder(0); normalizeScanStats(); #endif #if HHI_RQT #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif #endif } }
Void TDecSlice::decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic) { TComDataCU* pcCU; UInt uiIsLast = 0; #if FINE_GRANULARITY_SLICES Int iStartCUAddr = max(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr()/rpcPic->getNumPartInCU(), rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getEntropySliceCurStartCUAddr()/rpcPic->getNumPartInCU()); #else Int iStartCUAddr = max(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr(), rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getEntropySliceCurStartCUAddr()); #endif // decoder don't need prediction & residual frame buffer rpcPic->setPicYuvPred( 0 ); rpcPic->setPicYuvResi( 0 ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( rpcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif // for all CUs in slice UInt uiLastCUAddr = iStartCUAddr; for( Int iCUAddr = iStartCUAddr; !uiIsLast && iCUAddr < rpcPic->getNumCUsInFrame(); iCUAddr++, uiLastCUAddr++ ) { pcCU = rpcPic->getCU( iCUAddr ); pcCU->initCU( rpcPic, iCUAddr ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif m_pcCuDecoder->decodeCU ( pcCU, uiIsLast ); m_pcCuDecoder->decompressCU ( pcCU ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif } }
/** Create non-deblocked filter information * \param pSliceStartAddress array for storing slice start addresses * \param numSlices number of slices in picture * \param sliceGranularityDepth slice granularity * \param bNDBFilterCrossSliceBoundary cross-slice-boundary in-loop filtering; true for "cross". * \param numTiles number of tiles in picture * \param bNDBFilterCrossTileBoundary cross-tile-boundary in-loop filtering; true for "cross". */ Void TComPic::createNonDBFilterInfo(std::vector<Int> sliceStartAddress, Int sliceGranularityDepth ,std::vector<Bool>* LFCrossSliceBoundary ,Int numTiles ,Bool bNDBFilterCrossTileBoundary) { UInt maxNumSUInLCU = getNumPartInCU(); UInt numLCUInPic = getNumCUsInFrame(); UInt picWidth = getSlice(0)->getSPS()->getPicWidthInLumaSamples(); UInt picHeight = getSlice(0)->getSPS()->getPicHeightInLumaSamples(); Int numLCUsInPicWidth = getFrameWidthInCU(); Int numLCUsInPicHeight= getFrameHeightInCU(); UInt maxNumSUInLCUWidth = getNumPartInWidth(); UInt maxNumSUInLCUHeight= getNumPartInHeight(); Int numSlices = (Int) sliceStartAddress.size() - 1; m_bIndependentSliceBoundaryForNDBFilter = false; if(numSlices > 1) { for(Int s=0; s< numSlices; s++) { if((*LFCrossSliceBoundary)[s] == false) { m_bIndependentSliceBoundaryForNDBFilter = true; } } } m_sliceGranularityForNDBFilter = sliceGranularityDepth; m_bIndependentTileBoundaryForNDBFilter = (bNDBFilterCrossTileBoundary)?(false) :((numTiles > 1)?(true):(false)); m_pbValidSlice = new Bool[numSlices]; for(Int s=0; s< numSlices; s++) { m_pbValidSlice[s] = true; } m_pSliceSUMap = new Int[maxNumSUInLCU * numLCUInPic]; //initialization for(UInt i=0; i< (maxNumSUInLCU * numLCUInPic); i++ ) { m_pSliceSUMap[i] = -1; } for( UInt CUAddr = 0; CUAddr < numLCUInPic ; CUAddr++ ) { TComDataCU* pcCU = getCU( CUAddr ); pcCU->setSliceSUMap(m_pSliceSUMap + (CUAddr* maxNumSUInLCU)); pcCU->getNDBFilterBlocks()->clear(); } m_vSliceCUDataLink.clear(); m_vSliceCUDataLink.resize(numSlices); UInt startAddr, endAddr, firstCUInStartLCU, startLCU, endLCU, lastCUInEndLCU, uiAddr; UInt LPelX, TPelY, LCUX, LCUY; UInt currSU; UInt startSU, endSU; for(Int s=0; s< numSlices; s++) { //1st step: decide the real start address startAddr = sliceStartAddress[s]; endAddr = sliceStartAddress[s+1] -1; startLCU = startAddr / maxNumSUInLCU; firstCUInStartLCU = startAddr % maxNumSUInLCU; endLCU = endAddr / maxNumSUInLCU; lastCUInEndLCU = endAddr % maxNumSUInLCU; uiAddr = m_apcPicSym->getCUOrderMap(startLCU); LCUX = getCU(uiAddr)->getCUPelX(); LCUY = getCU(uiAddr)->getCUPelY(); LPelX = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[firstCUInStartLCU] ]; TPelY = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[firstCUInStartLCU] ]; currSU = firstCUInStartLCU; Bool bMoveToNextLCU = false; Bool bSliceInOneLCU = (startLCU == endLCU); while(!( LPelX < picWidth ) || !( TPelY < picHeight )) { currSU ++; if(bSliceInOneLCU) { if(currSU > lastCUInEndLCU) { m_pbValidSlice[s] = false; break; } } if(currSU >= maxNumSUInLCU ) { bMoveToNextLCU = true; break; } LPelX = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ]; TPelY = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ]; } if(!m_pbValidSlice[s]) { continue; } if(currSU != firstCUInStartLCU) { if(!bMoveToNextLCU) { firstCUInStartLCU = currSU; } else { startLCU++; firstCUInStartLCU = 0; assert( startLCU < getNumCUsInFrame()); } assert(startLCU*maxNumSUInLCU + firstCUInStartLCU < endAddr); } //2nd step: assign NonDBFilterInfo to each processing block for(UInt i= startLCU; i <= endLCU; i++) { startSU = (i == startLCU)?(firstCUInStartLCU):(0); endSU = (i == endLCU )?(lastCUInEndLCU ):(maxNumSUInLCU -1); uiAddr = m_apcPicSym->getCUOrderMap(i); Int iTileID= m_apcPicSym->getTileIdxMap(uiAddr); TComDataCU* pcCU = getCU(uiAddr); m_vSliceCUDataLink[s].push_back(pcCU); createNonDBFilterInfoLCU(iTileID, s, pcCU, startSU, endSU, m_sliceGranularityForNDBFilter, picWidth, picHeight); } } //step 3: border availability for(Int s=0; s< numSlices; s++) { if(!m_pbValidSlice[s]) { continue; } for(Int i=0; i< m_vSliceCUDataLink[s].size(); i++) { TComDataCU* pcCU = m_vSliceCUDataLink[s][i]; uiAddr = pcCU->getAddr(); if(pcCU->getPic()==0) { continue; } Int iTileID= m_apcPicSym->getTileIdxMap(uiAddr); Bool bTopTileBoundary = false, bDownTileBoundary= false, bLeftTileBoundary= false, bRightTileBoundary= false; if(m_bIndependentTileBoundaryForNDBFilter) { //left if( uiAddr % numLCUsInPicWidth != 0) { bLeftTileBoundary = ( m_apcPicSym->getTileIdxMap(uiAddr -1) != iTileID )?true:false; } //right if( (uiAddr % numLCUsInPicWidth) != (numLCUsInPicWidth -1) ) { bRightTileBoundary = ( m_apcPicSym->getTileIdxMap(uiAddr +1) != iTileID)?true:false; } //top if( uiAddr >= numLCUsInPicWidth) { bTopTileBoundary = (m_apcPicSym->getTileIdxMap(uiAddr - numLCUsInPicWidth) != iTileID )?true:false; } //down if( uiAddr + numLCUsInPicWidth < numLCUInPic ) { bDownTileBoundary = (m_apcPicSym->getTileIdxMap(uiAddr + numLCUsInPicWidth) != iTileID)?true:false; } } pcCU->setNDBFilterBlockBorderAvailability(numLCUsInPicWidth, numLCUsInPicHeight, maxNumSUInLCUWidth, maxNumSUInLCUHeight,picWidth, picHeight , *LFCrossSliceBoundary ,bTopTileBoundary, bDownTileBoundary, bLeftTileBoundary, bRightTileBoundary ,m_bIndependentTileBoundaryForNDBFilter); } } if( m_bIndependentSliceBoundaryForNDBFilter || m_bIndependentTileBoundaryForNDBFilter) { m_pNDBFilterYuvTmp = new TComPicYuv(); m_pNDBFilterYuvTmp->create(picWidth, picHeight, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth); } }
//index== 0 above 1 left 2 above and left 3 above and right Int GolombCode_Predict_SingleNeighbor(TComYuv *pcResiYuv, TComTU& rTu, const ComponentID compID, UInt uiCUHandleAddr, UInt uiAIndex, TCoeff* pcCoeff) { const Bool bIsLuma = isLuma(compID); const TComRectangle &rect = rTu.getRect(compID); TComDataCU *pcCU = rTu.getCU(); UInt uiCUAddr = pcCU->getCtuRsAddr(); //if ((int)uiCUHandleAddr < 0) return -1; TComPicYuv *pcPicYuvResi = pcCU->getPic()->getPicYuvResi(); if (pcPicYuvResi == NULL) return -1; const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); // const UInt uiZOrder = pcCU->getZorderIdxInCU() +uiAbsPartIdx; const UInt uiTrDepth = rTu.GetTransformDepthRelAdj(compID); const UInt uiFullDepth = rTu.GetTransformDepthTotal(); const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); const ChromaFormat chFmt = pcCU->getPic()->getChromaFormat(); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; const UInt uiStride = pcResiYuv->getStride(compID); UInt uiAddr = pcCU->getCtuRsAddr(); TComYuv *pcTemp; pcTemp = new TComYuv; UInt uiSrc1Stride = pcPicYuvResi->getStride(compID); UInt CUPelX, CUPelY; CUPelX = (uiCUHandleAddr % pcCU->getPic()->getFrameWidthInCtus()) * g_uiMaxCUWidth; CUPelY = (uiCUHandleAddr / pcCU->getPic()->getFrameWidthInCtus()) * g_uiMaxCUHeight; CUPelX = CUPelX + g_auiRasterToPelX[g_auiZscanToRaster[uiAbsPartIdx]]; CUPelY = CUPelY + g_auiRasterToPelY[g_auiZscanToRaster[uiAbsPartIdx]]; //for(int m=0;m<256;m++) cout<<g_auiZscanToRaster[m] <<" ";cout<<endl; //for(int m=0;m<256;m++) cout<<g_auiRasterToPelX[m] <<" ";cout<<endl; //for(int m=0;m<256;m++) cout<<g_auiRasterToPelY[m] <<" ";cout<<endl; //Pel *pSrc1 = pcPicYuvResi->getAddr(compID) +CUPelY * uiSrc1Stride + CUPelX; Pel *pSrc1 = pcPicYuvResi->getAddr(compID, uiCUHandleAddr, uiAbsPartIdx + pcCU->getZorderIdxInCtu()); /* if( compID != COMPONENT_Y) { pSrc1 = pcPicYuvResi->getAddr(COMPONENT_Y, uiCUHandleAddr, uiAbsPartIdx + pcCU->getZorderIdxInCU()); }*/ pcTemp->create(uiWidth, uiHeight, chFmt); // pcTemp->copyFromPicComponent(compID,pcPicYuvResi,uiCUHandleAddr, pcCU->getZorderIdxInCU()+uiAbsPartIdx); UInt uiTempStride = pcTemp->getStride(compID); Pel *pTemp = pcTemp->getAddr(compID); for (Int y = 0; y < uiHeight; y++) { for (Int x = 0; x < uiWidth; x++) { pTemp[x] = pSrc1[x]; } pTemp += uiTempStride; pSrc1 += uiSrc1Stride; } int srclx = 0; int srcly = 0; int srclv = 0; int srchasleft = 1; Pel srcpel; int srclist[3][64 * 64]; int srcindex = 0; memset(srclist, -1, 3 * 64 * 64 * sizeof(int)); int cursrclistindex = 0; Pel* piSrc = pcTemp->getAddr(compID); //Pel* piSrc = pcTemp->getAddr(compID, uiAbsPartIdx); Pel* pSrc = piSrc; //found the source list while (srchasleft) { int ndis = 1000; int nx = -1; int ny = -1; pSrc = piSrc; for (UInt y = 0; y < uiHeight; y++) { for (UInt x = 0; x<uiWidth; x++) { assert(pSrc[x] >-256 && pSrc[x] < 256); if (pSrc[x] != 0) { int dis = 0; dis += getG0Bits((x - srclx)); dis += getG0Bits((y - srcly)); if (dis < ndis) { nx = x; ny = y; ndis = dis; } } } pSrc += uiTempStride; } if (nx != -1 && ny != -1) { srcpel = *(piSrc + ny*uiTempStride + nx); srclx = nx; srcly = ny; srclv = srcpel; srclist[0][srcindex] = srclx; srclist[1][srcindex] = srcly; srclist[2][srcindex] = srcpel; srcindex++; *(piSrc + ny*uiTempStride + nx) = 0; } else { srchasleft = 0; } } if (srcindex == 0) { pcTemp->destroy(); delete pcTemp; pcTemp = NULL; return -1; } //// TComPicYuv *pcPicOrg = pcCU->getPic()->getPicYuvOrg(); Pel* piOrg = pcPicOrg->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx); const UInt uiOrgStride = pcPicOrg->getStride(compID); //// Pel* piResi = pcResiYuv->getAddr(compID, uiAbsPartIdx); Pel* pResi = piResi; int dstindex = 0; int indexlist[64 * 64][5]; memset(indexlist, 0, 5 * 64 * 64 * sizeof(int)); int contz = 0; int contnz = 0; int cs = 0; int bits = 0; // int temp; int lx = 0; int ly = 0; int lv = 0; int hasleft = 1; Pel pel; while (hasleft) { //found the least distance point int ndis = 1000; int nx = -1; int ny = -1; pResi = piResi; for (UInt y = 0; y < uiHeight; y++) { for (UInt x = 0; x < uiWidth; x++) { if (pResi[x] != 0) { int dis = 0; dis += getG0Bits((x - lx)); dis += getG0Bits((y - ly)); if (dis < ndis) { nx = x; ny = y; ndis = dis; } } } pResi += uiStride; } if (nx != -1 && ny != -1) { pel = *(piResi + ny*uiStride + nx); int srcdis = 1024 * 4; int srccur = -1; for (UInt s = 0; s < srcindex; s++) { int curdis = 0; curdis += getG0Bits((nx - srclist[0][s])); curdis += getG0Bits((ny - srclist[1][s])); // curdis += getG0Bits( (pel-srclist[2][s]));// getG0Bits can handle -512 && 512 if (curdis < srcdis) { srccur = s; srcdis = curdis; } } if (srccur != -1) { indexlist[dstindex][0] = nx - srclist[0][srccur]; indexlist[dstindex][1] = ny - srclist[1][srccur]; assert(pel != 0); indexlist[dstindex][4] = srccur; dstindex++; cursrclistindex = srccur; } else { assert(true); } lx = nx; ly = ny; lv = pel; *(piResi + ny*uiStride + nx) = 0; } else { hasleft = 0; } } pcTemp->destroy(); delete pcTemp; pcTemp = NULL; if (dstindex == 0) { assert(bits == 0); return bits; } qsort(indexlist, dstindex, sizeof(int)* 5, compare5); for (UInt x = dstindex - 1; x > 0; x--) { indexlist[x][4] -= indexlist[x - 1][4]; } //bits += getG0Bits( (indexlist[0][0])); //bits += getG0Bits( (indexlist[0][1])); int maxlength = 0; UInt truebits = 0; bool vlcf[3] = { false, false, false };// dx & dy residual srcindex int z01 = 0; for (UInt x = 1; x < dstindex; x++) { if (indexlist[x][0] == indexlist[x - 1][0] && indexlist[x][1] == indexlist[x - 1][1]) { maxlength++; } else { bits += getG0Bits((maxlength)); bits += getG0Bits((indexlist[x - 1][0])); bits += getG0Bits((indexlist[x - 1][1])); maxlength = 0; } if (indexlist[x][0] == 0 && indexlist[x][1] == 0) z01++; } bits += getG0Bits((maxlength)); bits += getG0Bits((indexlist[dstindex - 1][0])); bits += getG0Bits((indexlist[dstindex - 1][1])); UInt sbits = 0; for (UInt x = 0; x < dstindex; x++) { sbits += getG0Bits((indexlist[x][0])); sbits += getG0Bits((indexlist[x][1])); } // printf("gain %6d position before %6d after %6d\n",sbits-bits,sbits,bits); if (sbits < bits) { vlcf[0] = true; bits = sbits; } sbits = bits + 1; //bits += getG0Bits( PTable(compID,indexlist[0][2])); { maxlength = 0; for (UInt x = 1; x < dstindex; x++) { if (indexlist[x][2] == indexlist[x - 1][2] && indexlist[x][3] == indexlist[x - 1][3]) { maxlength++; } else { bits += getG0Bits((maxlength)); bits += getG0Bits(indexlist[x - 1][3]); bits += getG0Bits(indexlist[x - 1][2]); maxlength = 0; } } bits += getG0Bits((maxlength)); bits += getG0Bits(indexlist[dstindex - 1][3]); bits += getG0Bits((indexlist[dstindex - 1][2])); } UInt vbits = 0; sbits = bits - sbits; for (UInt x = 0; x < dstindex; x++) { { vbits += getG0Bits(indexlist[x][2]); vbits += getG0Bits(indexlist[x][3]); } } // printf("gain %6d delta resi before %6d after %6d\n",vbits-sbits,vbits,sbits); if (vbits < sbits) { vlcf[1] = true; bits = bits - sbits + vbits; } sbits = bits + 1; //bits += getG0Bits( (indexlist[0][3])); Int srcPosIndex; srcPosIndex = 4; maxlength = 0; for (UInt x = 1; x < dstindex; x++) { if (indexlist[x][srcPosIndex] == indexlist[x - 1][srcPosIndex]) { maxlength++; } else { bits += getG0Bits((maxlength)); bits += getG0Bits((indexlist[x - 1][srcPosIndex])); maxlength = 0; } } bits += getG0Bits((maxlength)); bits += getG0Bits((indexlist[dstindex - 1][srcPosIndex])); sbits = bits - sbits; vbits = 0; for (UInt x = 0; x < dstindex; x++) { vbits += getG0Bits((indexlist[x][srcPosIndex])); } // printf("gain %6d delta index before %6d after %6d\n",vbits-sbits,vbits,sbits); if (vbits < sbits) { vlcf[2] = true; bits = bits - sbits + vbits; } //#if INTRA_PR_DEBUG // if( pcCU->getAddr()==INTRA_PR_CUNUM ) // printf("position distance zero %6d of %6d total bits %6d\n",z01,dstindex,bits+1); //#endif truebits = 0; ExpGolombEncode(uiAIndex, pcCoeff, truebits); //--------------encode srcindex if (vlcf[2]) { ExpGolombEncode(0, pcCoeff, truebits); for (UInt x = 0; x < dstindex; x++) { //cout<<" "<<indexlist[x][3] ; ExpGolombEncode((indexlist[x][srcPosIndex]), pcCoeff, truebits); } } else{ ExpGolombEncode(1, pcCoeff, truebits); maxlength = 0; for (UInt x = 1; x<dstindex; x++) { if (indexlist[x][srcPosIndex] == indexlist[x - 1][srcPosIndex]) { maxlength++; } else { ExpGolombEncode((maxlength), pcCoeff, truebits); ExpGolombEncode((indexlist[x - 1][srcPosIndex]), pcCoeff, truebits); maxlength = 0; } } assert(maxlength>-1); ExpGolombEncode((maxlength), pcCoeff, truebits); ExpGolombEncode((indexlist[dstindex - 1][srcPosIndex]), pcCoeff, truebits); } ExpGolombEncode(-1, pcCoeff, truebits); //---------------encode residual if (vlcf[1]) { ExpGolombEncode(0, pcCoeff, truebits); for (UInt x = 0; x < dstindex; x++) { { ExpGolombEncode(indexlist[x][2], pcCoeff, truebits); // if( !bNoResidual) // ExpGolombEncode( indexlist[x][3],pcCoeff,truebits); } } } else{ ExpGolombEncode(1, pcCoeff, truebits); //ExpGolombEncode( (indexlist[0][2]),pcCoeff,truebits); maxlength = 0; { for (UInt x = 1; x < dstindex; x++) { if (indexlist[x][2] == indexlist[x - 1][2] && indexlist[x][3] == indexlist[x - 1][3]) { maxlength++; } else { ExpGolombEncode((maxlength), pcCoeff, truebits); //assert( (maxlength)>=0); ExpGolombEncode(indexlist[x - 1][2], pcCoeff, truebits); // if( !bNoResidual) // ExpGolombEncode( indexlist[x-1][3],pcCoeff,truebits); maxlength = 0; } } ExpGolombEncode((maxlength), pcCoeff, truebits); ExpGolombEncode(indexlist[dstindex - 1][2], pcCoeff, truebits); //if( !bNoResidual) // ExpGolombEncode( indexlist[dstindex-1][3] , pcCoeff, truebits); } } //--------------encode dx and dy ----------- if (vlcf[0]) { ExpGolombEncode(0, pcCoeff, truebits); for (UInt x = 0; x < dstindex; x++) { ExpGolombEncode((indexlist[x][0]), pcCoeff, truebits); ExpGolombEncode((indexlist[x][1]), pcCoeff, truebits); } } else{ ExpGolombEncode(1, pcCoeff, truebits); //ExpGolombEncode( (indexlist[0][0]),pcCoeff,truebits); //ExpGolombEncode( (indexlist[0][1]),pcCoeff,truebits); maxlength = 0; for (UInt x = 1; x < dstindex; x++) { if (indexlist[x][0] == indexlist[x - 1][0] && indexlist[x][1] == indexlist[x - 1][1]) { maxlength++; } else { ExpGolombEncode((maxlength), pcCoeff, truebits); ExpGolombEncode((indexlist[x - 1][0]), pcCoeff, truebits); ExpGolombEncode((indexlist[x - 1][1]), pcCoeff, truebits); maxlength = 0; } } ExpGolombEncode((maxlength), pcCoeff, truebits); ExpGolombEncode((indexlist[dstindex - 1][0]), pcCoeff, truebits); ExpGolombEncode((indexlist[dstindex - 1][1]), pcCoeff, truebits); } return truebits;/* bits +1*/; }
UInt PositionCode_Predict(TComYuv *pcResiYuv, TComTU& rTu, const ComponentID compID, TCoeff* pcCoeff /*,Bool bMV,bool bNoResidual*/) { if (!rTu.ProcessComponentSection(compID)) return -1; TComDataCU *pcCU = rTu.getCU(); UInt uiCUAddr = pcCU->getCtuRsAddr(); UInt uiFrameWidthInCU = pcCU->getPic()->getFrameWidthInCtus(); UInt uiCUAboveAddr = uiCUAddr - uiFrameWidthInCU; UInt uiCULeftAddr = uiCUAddr - 1; UInt uiCUAboveLeftAddr = uiCUAddr - 1 - uiFrameWidthInCU; UInt uiCUAboveRightAddr = uiCUAddr + 1 - uiFrameWidthInCU; UInt uiCUArray[4] = { uiCULeftAddr, uiCUAboveAddr, uiCUAboveLeftAddr, uiCUAboveRightAddr }; UInt uiCUHandleAddr; Int curindex, minibits, temp/*,truebits*/; TCoeff pcCoeffTemp[MAX_BUFFER]; TComYuv *pcComYuv = new TComYuv; const TComRectangle &rect = rTu.getRect(compID); UInt uiTempStride, uiSrcStride; uiSrcStride = pcResiYuv->getStride(compID); UInt uiHeight = pcResiYuv->getHeight(compID); UInt uiWidth = pcResiYuv->getWidth(compID); pcComYuv->create(uiWidth, uiHeight, pcCU->getPic()->getChromaFormat()); uiTempStride = pcComYuv->getStride(compID); //memset(pcCoeffTemp,0,sizeof(TCoeff)*MAX_BUFFER); minibits = MAX_INT; for (UInt index = 0; index < 4; index++) { uiCUHandleAddr = uiCUArray[index]; if ((int)uiCUHandleAddr < 0) continue; pcComYuv->clear(); for (UInt y = 0; y < uiHeight; y++) { for (UInt x = 0; x<uiWidth; x++) { *(pcComYuv->getAddr(compID) + y*uiTempStride + x) = *(pcResiYuv->getAddr(compID) + y*uiSrcStride + x); } } //pcResiYuv->copyToPartComponent ( compID, pcComYuv, 0); memset(pcCoeffTemp, 0, sizeof(TCoeff)*MAX_BUFFER); //_CrtMemState s1,s2,s3; //_CrtMemCheckpoint( &s1 ); temp = GolombCode_Predict_SingleNeighbor(pcComYuv, rTu, compID, uiCUHandleAddr, index, pcCoeffTemp); if (temp> -1 && temp < minibits) { curindex = index;//uiCUHandleAddr; minibits = temp; //truebits = minibits / GOLOMB_EXP_BUFFER + ( (minibits % GOLOMB_EXP_BUFFER==0) ? 0:1 ); memcpy(pcCoeff, pcCoeffTemp, sizeof(TCoeff)*rect.height*rect.width/* truebits*/); } //_CrtMemCheckpoint( &s2 ); //if ( _CrtMemDifference( &s3, &s1, &s2) ) //{ // _CrtMemDumpStatistics( &s3 ); // _CrtDumpMemoryLeaks(); //} } pcComYuv->destroy(); delete pcComYuv; pcComYuv = NULL; if (minibits != MAX_INT) { assert(uiCUArray[curindex] >= 0); return minibits; } return MAX_UINT; }
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 TComPic::createNonDBFilterInfo(UInt* puiSliceStartAddress, Int iNumSlices, Int iSliceGranularityDepth ,Bool bNDBFilterCrossSliceBoundary ,Int iNumTiles ,Bool bNDBFilterCrossTileBoundary) { UInt uiMaxNumSUInLCU = getNumPartInCU(); UInt uiNumLCUInPic = getNumCUsInFrame(); UInt uiPicWidth = getCU(0)->getSlice()->getSPS()->getWidth(); UInt uiPicHeight = getCU(0)->getSlice()->getSPS()->getHeight(); Int iNumLCUsInPicWidth = getFrameWidthInCU(); Int iNumLCUsInPicHeight= getFrameHeightInCU(); UInt uiMaxNumSUInLCUWidth = getNumPartInWidth(); UInt uiMAxNumSUInLCUHeight= getNumPartInHeight(); m_bIndependentSliceBoundaryForNDBFilter = (bNDBFilterCrossSliceBoundary)?(false):((iNumSlices > 1)?(true):(false)) ; m_iSliceGranularityForNDBFilter = iSliceGranularityDepth; m_bIndependentTileBoundaryForNDBFilter = (bNDBFilterCrossTileBoundary)?(false) :((iNumTiles > 1)?(true):(false)); m_pbValidSlice = new Bool[iNumSlices]; for(Int s=0; s< iNumSlices; s++) { m_pbValidSlice[s] = true; } if( puiSliceStartAddress == NULL || (iNumSlices == 1 && iNumTiles == 1) ) { return; } m_piSliceSUMap = new Int[uiMaxNumSUInLCU * uiNumLCUInPic]; //initialization for(UInt i=0; i< (uiMaxNumSUInLCU * uiNumLCUInPic); i++ ) { m_piSliceSUMap[i] = -1; } for( UInt uiCUAddr = 0; uiCUAddr < uiNumLCUInPic ; uiCUAddr++ ) { TComDataCU* pcCU = getCU( uiCUAddr ); pcCU->setSliceSUMap(m_piSliceSUMap + (uiCUAddr* uiMaxNumSUInLCU)); pcCU->getNDBFilterBlocks()->clear(); } m_vSliceCUDataLink.clear(); m_vSliceCUDataLink.resize(iNumSlices); UInt uiStartAddr, uiEndAddr, uiFirstCUInStartLCU, uiStartLCU, uiEndLCU, uiLastCUInEndLCU, uiAddr; UInt uiLPelX, uiTPelY, uiLCUX, uiLCUY; UInt uiCurrSU; UInt uiStartSU, uiEndSU; for(Int s=0; s< iNumSlices; s++) { //1st step: decide the real start address #if FINE_GRANULARITY_SLICES uiStartAddr = puiSliceStartAddress[s]; uiEndAddr = puiSliceStartAddress[s+1] -1; #else uiStartAddr = (puiSliceStartAddress[s]*uiMaxNumSUInLCU); uiEndAddr = (puiSliceStartAddress[s+1]*uiMaxNumSUInLCU) -1; #endif uiStartLCU = uiStartAddr / uiMaxNumSUInLCU; uiFirstCUInStartLCU = uiStartAddr % uiMaxNumSUInLCU; uiEndLCU = uiEndAddr / uiMaxNumSUInLCU; uiLastCUInEndLCU = uiEndAddr % uiMaxNumSUInLCU; #if TILES uiAddr = m_apcPicSym->getCUOrderMap(uiStartLCU); #else uiAddr = uiStartLCU; #endif uiLCUX = getCU(uiAddr)->getCUPelX(); uiLCUY = getCU(uiAddr)->getCUPelY(); uiLPelX = uiLCUX + g_auiRasterToPelX[ g_auiZscanToRaster[uiFirstCUInStartLCU] ]; uiTPelY = uiLCUY + g_auiRasterToPelY[ g_auiZscanToRaster[uiFirstCUInStartLCU] ]; uiCurrSU = uiFirstCUInStartLCU; Bool bMoveToNextLCU = false; Bool bSliceInOneLCU = (uiStartLCU == uiEndLCU); while(!( uiLPelX < uiPicWidth ) || !( uiTPelY < uiPicHeight )) { uiCurrSU ++; if(bSliceInOneLCU) { if(uiCurrSU > uiLastCUInEndLCU) { m_pbValidSlice[s] = false; break; } } if(uiCurrSU >= uiMaxNumSUInLCU ) { bMoveToNextLCU = true; break; } uiLPelX = uiLCUX + g_auiRasterToPelX[ g_auiZscanToRaster[uiCurrSU] ]; uiTPelY = uiLCUY + g_auiRasterToPelY[ g_auiZscanToRaster[uiCurrSU] ]; } if(!m_pbValidSlice[s]) { continue; } if(uiCurrSU != uiFirstCUInStartLCU) { if(!bMoveToNextLCU) { uiFirstCUInStartLCU = uiCurrSU; } else { uiStartLCU++; uiFirstCUInStartLCU = 0; assert( uiStartLCU < getNumCUsInFrame()); } assert(uiStartLCU*uiMaxNumSUInLCU + uiFirstCUInStartLCU < uiEndAddr); } //2nd step: assign NonDBFilterInfo to each processing block for(UInt i= uiStartLCU; i <= uiEndLCU; i++) { uiStartSU = (i == uiStartLCU)?(uiFirstCUInStartLCU):(0); uiEndSU = (i == uiEndLCU )?(uiLastCUInEndLCU ):(uiMaxNumSUInLCU -1); #if TILES uiAddr = m_apcPicSym->getCUOrderMap(i); Int iTileID= m_apcPicSym->getTileIdxMap(uiAddr); #else uiAddr = i; #endif TComDataCU* pcCU = getCU(uiAddr); m_vSliceCUDataLink[s].push_back(pcCU); #if TILES createNonDBFilterInfoLCU(iTileID, s, pcCU, uiStartSU, uiEndSU, m_iSliceGranularityForNDBFilter, uiPicWidth, uiPicHeight); #else createNonDBFilterInfoLCU(s, pcCU, uiStartSU, uiEndSU, m_iSliceGranularityForNDBFilter, uiPicWidth, uiPicHeight); #endif } } //step 3: border availability for(Int s=0; s< iNumSlices; s++) { if(!m_pbValidSlice[s]) { continue; } for(Int i=0; i< m_vSliceCUDataLink[s].size(); i++) { TComDataCU* pcCU = m_vSliceCUDataLink[s][i]; uiAddr = pcCU->getAddr(); Int iTileID= m_apcPicSym->getTileIdxMap(uiAddr); Bool bTopTileBoundary = false, bDownTileBoundary= false, bLeftTileBoundary= false, bRightTileBoundary= false; if(m_bIndependentTileBoundaryForNDBFilter) { //left if( uiAddr % iNumLCUsInPicWidth != 0) { bLeftTileBoundary = ( m_apcPicSym->getTileIdxMap(uiAddr -1) != iTileID )?true:false; } //right if( (uiAddr % iNumLCUsInPicWidth) != (iNumLCUsInPicWidth -1) ) { bRightTileBoundary = ( m_apcPicSym->getTileIdxMap(uiAddr +1) != iTileID)?true:false; } //top if( uiAddr >= iNumLCUsInPicWidth) { bTopTileBoundary = (m_apcPicSym->getTileIdxMap(uiAddr - iNumLCUsInPicWidth) != iTileID )?true:false; } //down if( uiAddr + iNumLCUsInPicWidth < uiNumLCUInPic ) { bDownTileBoundary = (m_apcPicSym->getTileIdxMap(uiAddr + iNumLCUsInPicWidth) != iTileID)?true:false; } } pcCU->setNDBFilterBlockBorderAvailability(iNumLCUsInPicWidth, iNumLCUsInPicHeight, uiMaxNumSUInLCUWidth, uiMAxNumSUInLCUHeight,uiPicWidth, uiPicHeight ,m_bIndependentSliceBoundaryForNDBFilter ,bTopTileBoundary, bDownTileBoundary, bLeftTileBoundary, bRightTileBoundary ,m_bIndependentTileBoundaryForNDBFilter); } } if( m_bIndependentSliceBoundaryForNDBFilter || m_bIndependentTileBoundaryForNDBFilter) { m_pcNDBFilterYuvTmp = new TComPicYuv(); m_pcNDBFilterYuvTmp->create(uiPicWidth, uiPicHeight, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth); } }
Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic*& rpcPic, TDecSbac* pcSbacDecoder, TDecSbac* pcSbacDecoders) { TComDataCU* pcCU; UInt uiIsLast = 0; Int iStartCUEncOrder = max(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr()/rpcPic->getNumPartInCU(), rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceSegmentCurStartCUAddr()/rpcPic->getNumPartInCU()); Int iStartCUAddr = rpcPic->getPicSym()->getCUOrderMap(iStartCUEncOrder); // decoder don't need prediction & residual frame buffer #if ENABLE_ANAYSIS_OUTPUT #else rpcPic->setPicYuvPred( 0 ); rpcPic->setPicYuvResi( 0 ); #endif #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( rpcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif UInt uiTilesAcross = rpcPic->getPicSym()->getNumColumnsMinus1()+1; TComSlice* pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx()); Int iNumSubstreams = pcSlice->getPPS()->getNumSubstreams(); // delete decoders if already allocated in previous slice if (m_pcBufferSbacDecoders) { delete [] m_pcBufferSbacDecoders; } if (m_pcBufferBinCABACs) { delete [] m_pcBufferBinCABACs; } // allocate new decoders based on tile numbaer m_pcBufferSbacDecoders = new TDecSbac [uiTilesAcross]; m_pcBufferBinCABACs = new TDecBinCABAC[uiTilesAcross]; for (UInt ui = 0; ui < uiTilesAcross; ui++) { m_pcBufferSbacDecoders[ui].init(&m_pcBufferBinCABACs[ui]); } //save init. state for (UInt ui = 0; ui < uiTilesAcross; ui++) { m_pcBufferSbacDecoders[ui].load(pcSbacDecoder); } // free memory if already allocated in previous call if (m_pcBufferLowLatSbacDecoders) { delete [] m_pcBufferLowLatSbacDecoders; } if (m_pcBufferLowLatBinCABACs) { delete [] m_pcBufferLowLatBinCABACs; } m_pcBufferLowLatSbacDecoders = new TDecSbac [uiTilesAcross]; m_pcBufferLowLatBinCABACs = new TDecBinCABAC[uiTilesAcross]; for (UInt ui = 0; ui < uiTilesAcross; ui++) { m_pcBufferLowLatSbacDecoders[ui].init(&m_pcBufferLowLatBinCABACs[ui]); } //save init. state for (UInt ui = 0; ui < uiTilesAcross; ui++) { m_pcBufferLowLatSbacDecoders[ui].load(pcSbacDecoder); } UInt uiWidthInLCUs = rpcPic->getPicSym()->getFrameWidthInCU(); //UInt uiHeightInLCUs = rpcPic->getPicSym()->getFrameHeightInCU(); UInt uiCol=0, uiLin=0, uiSubStrm=0; UInt uiTileCol; UInt uiTileStartLCU; UInt uiTileLCUX; Int iNumSubstreamsPerTile = 1; // if independent. Bool depSliceSegmentsEnabled = rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getPPS()->getDependentSliceSegmentsEnabledFlag(); uiTileStartLCU = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iStartCUAddr))->getFirstCUAddr(); if( depSliceSegmentsEnabled ) { if( (!rpcPic->getSlice(rpcPic->getCurrSliceIdx())->isNextSlice()) && iStartCUAddr != rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iStartCUAddr))->getFirstCUAddr()) { if(pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag()) { uiTileCol = rpcPic->getPicSym()->getTileIdxMap(iStartCUAddr) % (rpcPic->getPicSym()->getNumColumnsMinus1()+1); m_pcBufferSbacDecoders[uiTileCol].loadContexts( CTXMem[1] );//2.LCU if ( (iStartCUAddr%uiWidthInLCUs+1) >= uiWidthInLCUs ) { uiTileLCUX = uiTileStartLCU % uiWidthInLCUs; uiCol = iStartCUAddr % uiWidthInLCUs; if(uiCol==uiTileLCUX) { CTXMem[0]->loadContexts(pcSbacDecoder); } } } pcSbacDecoder->loadContexts(CTXMem[0] ); //end of depSlice-1 pcSbacDecoders[uiSubStrm].loadContexts(pcSbacDecoder); } else { if(pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag()) { CTXMem[1]->loadContexts(pcSbacDecoder); } CTXMem[0]->loadContexts(pcSbacDecoder); } } for( Int iCUAddr = iStartCUAddr; !uiIsLast && iCUAddr < rpcPic->getNumCUsInFrame(); iCUAddr = rpcPic->getPicSym()->xCalculateNxtCUAddr(iCUAddr) ) { pcCU = rpcPic->getCU( iCUAddr ); pcCU->initCU( rpcPic, iCUAddr ); uiTileCol = rpcPic->getPicSym()->getTileIdxMap(iCUAddr) % (rpcPic->getPicSym()->getNumColumnsMinus1()+1); // what column of tiles are we in? uiTileStartLCU = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iCUAddr))->getFirstCUAddr(); uiTileLCUX = uiTileStartLCU % uiWidthInLCUs; uiCol = iCUAddr % uiWidthInLCUs; // The 'line' is now relative to the 1st line in the slice, not the 1st line in the picture. uiLin = (iCUAddr/uiWidthInLCUs)-(iStartCUAddr/uiWidthInLCUs); // inherit from TR if necessary, select substream to use. if( (pcSlice->getPPS()->getNumSubstreams() > 1) || ( depSliceSegmentsEnabled && (uiCol == uiTileLCUX)&&(pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag()) )) { // independent tiles => substreams are "per tile". iNumSubstreams has already been multiplied. iNumSubstreamsPerTile = iNumSubstreams/rpcPic->getPicSym()->getNumTiles(); uiSubStrm = rpcPic->getPicSym()->getTileIdxMap(iCUAddr)*iNumSubstreamsPerTile + uiLin%iNumSubstreamsPerTile; m_pcEntropyDecoder->setBitstream( ppcSubstreams[uiSubStrm] ); // Synchronize cabac probabilities with upper-right LCU if it's available and we're at the start of a line. if (((pcSlice->getPPS()->getNumSubstreams() > 1) || depSliceSegmentsEnabled ) && (uiCol == uiTileLCUX)&&(pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag())) { // We'll sync if the TR is available. TComDataCU *pcCUUp = pcCU->getCUAbove(); UInt uiWidthInCU = rpcPic->getFrameWidthInCU(); TComDataCU *pcCUTR = NULL; if ( pcCUUp && ((iCUAddr%uiWidthInCU+1) < uiWidthInCU) ) { pcCUTR = rpcPic->getCU( iCUAddr - uiWidthInCU + 1 ); } UInt uiMaxParts = 1<<(pcSlice->getSPS()->getMaxCUDepth()<<1); if ( (true/*bEnforceSliceRestriction*/ && ((pcCUTR==NULL) || (pcCUTR->getSlice()==NULL) || ((pcCUTR->getSCUAddr()+uiMaxParts-1) < pcSlice->getSliceCurStartCUAddr()) || ((rpcPic->getPicSym()->getTileIdxMap( pcCUTR->getAddr() ) != rpcPic->getPicSym()->getTileIdxMap(iCUAddr))) )) ) { // TR not available. } else { // TR is available, we use it. pcSbacDecoders[uiSubStrm].loadContexts( &m_pcBufferSbacDecoders[uiTileCol] ); } } pcSbacDecoder->load(&pcSbacDecoders[uiSubStrm]); //this load is used to simplify the code (avoid to change all the call to pcSbacDecoders) } else if ( pcSlice->getPPS()->getNumSubstreams() <= 1 ) { // Set variables to appropriate values to avoid later code change. iNumSubstreamsPerTile = 1; } if ( (iCUAddr == rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iCUAddr))->getFirstCUAddr()) && // 1st in tile. (iCUAddr!=0) && (iCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr())/rpcPic->getNumPartInCU()) && (iCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceSegmentCurStartCUAddr())/rpcPic->getNumPartInCU()) ) // !1st in frame && !1st in slice { if (pcSlice->getPPS()->getNumSubstreams() > 1) { // We're crossing into another tile, tiles are independent. // When tiles are independent, we have "substreams per tile". Each substream has already been terminated, and we no longer // have to perform it here. // For TILES_DECODER, there can be a header at the start of the 1st substream in a tile. These are read when the substreams // are extracted, not here. } else { SliceType sliceType = pcSlice->getSliceType(); if (pcSlice->getCabacInitFlag()) { switch (sliceType) { case P_SLICE: // change initialization table to B_SLICE intialization sliceType = B_SLICE; break; case B_SLICE: // change initialization table to P_SLICE intialization sliceType = P_SLICE; break; default : // should not occur assert(0); } } m_pcEntropyDecoder->updateContextTables( sliceType, pcSlice->getSliceQp() ); } } #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif if ( pcSlice->getSPS()->getUseSAO() && (pcSlice->getSaoEnabledFlag()||pcSlice->getSaoEnabledFlagChroma()) ) { SAOParam *saoParam = rpcPic->getPicSym()->getSaoParam(); saoParam->bSaoFlag[0] = pcSlice->getSaoEnabledFlag(); if (iCUAddr == iStartCUAddr) { saoParam->bSaoFlag[1] = pcSlice->getSaoEnabledFlagChroma(); } Int numCuInWidth = saoParam->numCuInWidth; Int cuAddrInSlice = iCUAddr - rpcPic->getPicSym()->getCUOrderMap(pcSlice->getSliceCurStartCUAddr()/rpcPic->getNumPartInCU()); Int cuAddrUpInSlice = cuAddrInSlice - numCuInWidth; Int rx = iCUAddr % numCuInWidth; Int ry = iCUAddr / numCuInWidth; Int allowMergeLeft = 1; Int allowMergeUp = 1; if (rx!=0) { if (rpcPic->getPicSym()->getTileIdxMap(iCUAddr-1) != rpcPic->getPicSym()->getTileIdxMap(iCUAddr)) { allowMergeLeft = 0; } } if (ry!=0) { if (rpcPic->getPicSym()->getTileIdxMap(iCUAddr-numCuInWidth) != rpcPic->getPicSym()->getTileIdxMap(iCUAddr)) { allowMergeUp = 0; } } pcSbacDecoder->parseSaoOneLcuInterleaving(rx, ry, saoParam,pcCU, cuAddrInSlice, cuAddrUpInSlice, allowMergeLeft, allowMergeUp); } else if ( pcSlice->getSPS()->getUseSAO() ) { Int addr = pcCU->getAddr(); SAOParam *saoParam = rpcPic->getPicSym()->getSaoParam(); for (Int cIdx=0; cIdx<3; cIdx++) { SaoLcuParam *saoLcuParam = &(saoParam->saoLcuParam[cIdx][addr]); if ( ((cIdx == 0) && !pcSlice->getSaoEnabledFlag()) || ((cIdx == 1 || cIdx == 2) && !pcSlice->getSaoEnabledFlagChroma())) { saoLcuParam->mergeUpFlag = 0; saoLcuParam->mergeLeftFlag = 0; saoLcuParam->subTypeIdx = 0; saoLcuParam->typeIdx = -1; saoLcuParam->offset[0] = 0; saoLcuParam->offset[1] = 0; saoLcuParam->offset[2] = 0; saoLcuParam->offset[3] = 0; } } } #if ENABLE_ANAYSIS_OUTPUT UInt uiBefore = ppcSubstreams[uiSubStrm]->getByteLocation(); #endif m_pcCuDecoder->decodeCU ( pcCU, uiIsLast ); #if ENABLE_ANAYSIS_OUTPUT pcCU->getTotalBits() = ppcSubstreams[uiSubStrm]->getByteLocation() - uiBefore; #endif m_pcCuDecoder->decompressCU ( pcCU ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif pcSbacDecoders[uiSubStrm].load(pcSbacDecoder); //Store probabilities of second LCU in line into buffer if ( (uiCol == uiTileLCUX+1)&& (depSliceSegmentsEnabled || (pcSlice->getPPS()->getNumSubstreams() > 1)) && (pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag()) ) { m_pcBufferSbacDecoders[uiTileCol].loadContexts( &pcSbacDecoders[uiSubStrm] ); } if( uiIsLast && depSliceSegmentsEnabled ) { if (pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag()) { CTXMem[1]->loadContexts( &m_pcBufferSbacDecoders[uiTileCol] );//ctx 2.LCU } CTXMem[0]->loadContexts( pcSbacDecoder );//ctx end of dep.slice return; } } }
Void TDecSlice::decompressSlice(TComInputBitstream* pcBitstream, TComInputBitstream** ppcSubstreams, TComPic*& rpcPic, TDecSbac* pcSbacDecoder, TDecSbac* pcSbacDecoders) { TComDataCU* pcCU; UInt uiIsLast = 0; Int iStartCUEncOrder = max(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr()/rpcPic->getNumPartInCU(), rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getEntropySliceCurStartCUAddr()/rpcPic->getNumPartInCU()); Int iStartCUAddr = rpcPic->getPicSym()->getCUOrderMap(iStartCUEncOrder); // decoder don't need prediction & residual frame buffer rpcPic->setPicYuvPred( 0 ); rpcPic->setPicYuvResi( 0 ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( rpcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif UInt uiTilesAcross = rpcPic->getPicSym()->getNumColumnsMinus1()+1; TComSlice* pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx()); UInt iSymbolMode = pcSlice->getPPS()->getEntropyCodingMode(); Int iNumSubstreams = pcSlice->getPPS()->getNumSubstreams(); if( iSymbolMode ) { m_pcBufferSbacDecoders = new TDecSbac [uiTilesAcross]; m_pcBufferBinCABACs = new TDecBinCABAC[uiTilesAcross]; for (UInt ui = 0; ui < uiTilesAcross; ui++) { m_pcBufferSbacDecoders[ui].init(&m_pcBufferBinCABACs[ui]); } //save init. state for (UInt ui = 0; ui < uiTilesAcross; ui++) { m_pcBufferSbacDecoders[ui].load(pcSbacDecoder); } } if( iSymbolMode ) { m_pcBufferLowLatSbacDecoders = new TDecSbac [uiTilesAcross]; m_pcBufferLowLatBinCABACs = new TDecBinCABAC[uiTilesAcross]; for (UInt ui = 0; ui < uiTilesAcross; ui++) m_pcBufferLowLatSbacDecoders[ui].init(&m_pcBufferLowLatBinCABACs[ui]); //save init. state for (UInt ui = 0; ui < uiTilesAcross; ui++) m_pcBufferLowLatSbacDecoders[ui].load(pcSbacDecoder); } UInt uiWidthInLCUs = rpcPic->getPicSym()->getFrameWidthInCU(); //UInt uiHeightInLCUs = rpcPic->getPicSym()->getFrameHeightInCU(); UInt uiCol=0, uiLin=0, uiSubStrm=0; UInt uiTileCol; UInt uiTileStartLCU; UInt uiTileLCUX; UInt uiTileLCUY; UInt uiTileWidth; UInt uiTileHeight; Int iNumSubstreamsPerTile = 1; // if independent. for( Int iCUAddr = iStartCUAddr; !uiIsLast && iCUAddr < rpcPic->getNumCUsInFrame(); iCUAddr = rpcPic->getPicSym()->xCalculateNxtCUAddr(iCUAddr) ) { pcCU = rpcPic->getCU( iCUAddr ); pcCU->initCU( rpcPic, iCUAddr ); uiTileCol = rpcPic->getPicSym()->getTileIdxMap(iCUAddr) % (rpcPic->getPicSym()->getNumColumnsMinus1()+1); // what column of tiles are we in? uiTileStartLCU = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iCUAddr))->getFirstCUAddr(); uiTileLCUX = uiTileStartLCU % uiWidthInLCUs; uiTileLCUY = uiTileStartLCU / uiWidthInLCUs; uiTileWidth = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iCUAddr))->getTileWidth(); uiTileHeight = rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iCUAddr))->getTileHeight(); uiCol = iCUAddr % uiWidthInLCUs; uiLin = iCUAddr / uiWidthInLCUs; // inherit from TR if necessary, select substream to use. if( iSymbolMode && pcSlice->getPPS()->getNumSubstreams() > 1 ) { if (pcSlice->getPPS()->getNumSubstreams() > 1) { // independent tiles => substreams are "per tile". iNumSubstreams has already been multiplied. iNumSubstreamsPerTile = iNumSubstreams/rpcPic->getPicSym()->getNumTiles(); uiSubStrm = rpcPic->getPicSym()->getTileIdxMap(iCUAddr)*iNumSubstreamsPerTile + uiLin%iNumSubstreamsPerTile; } else { // dependent tiles => substreams are "per frame". uiSubStrm = uiLin % iNumSubstreams; } m_pcEntropyDecoder->setBitstream( ppcSubstreams[uiSubStrm] ); // Synchronize cabac probabilities with upper-right LCU if it's available and we're at the start of a line. if (pcSlice->getPPS()->getNumSubstreams() > 1 && uiCol == uiTileLCUX) { // We'll sync if the TR is available. TComDataCU *pcCUUp = pcCU->getCUAbove(); UInt uiWidthInCU = rpcPic->getFrameWidthInCU(); TComDataCU *pcCUTR = NULL; if ( pcCUUp && ((iCUAddr%uiWidthInCU+1) < uiWidthInCU) ) { pcCUTR = rpcPic->getCU( iCUAddr - uiWidthInCU + 1 ); } UInt uiMaxParts = 1<<(pcSlice->getSPS()->getMaxCUDepth()<<1); if ( (true/*bEnforceSliceRestriction*/ && ((pcCUTR==NULL) || (pcCUTR->getSlice()==NULL) || ((pcCUTR->getSCUAddr()+uiMaxParts-1) < pcSlice->getSliceCurStartCUAddr()) || ((rpcPic->getPicSym()->getTileIdxMap( pcCUTR->getAddr() ) != rpcPic->getPicSym()->getTileIdxMap(iCUAddr))) ))|| (true/*bEnforceEntropySliceRestriction*/ && ((pcCUTR==NULL) || (pcCUTR->getSlice()==NULL) || ((pcCUTR->getSCUAddr()+uiMaxParts-1) < pcSlice->getEntropySliceCurStartCUAddr()) || ((rpcPic->getPicSym()->getTileIdxMap( pcCUTR->getAddr() ) != rpcPic->getPicSym()->getTileIdxMap(iCUAddr))) )) ) { // TR not available. } else { // TR is available, we use it. pcSbacDecoders[uiSubStrm].loadContexts( &m_pcBufferSbacDecoders[uiTileCol] ); } } pcSbacDecoder->load(&pcSbacDecoders[uiSubStrm]); //this load is used to simplify the code (avoid to change all the call to pcSbacDecoders) } else if ( iSymbolMode && pcSlice->getPPS()->getNumSubstreams() <= 1 ) { // Set variables to appropriate values to avoid later code change. iNumSubstreamsPerTile = 1; } if ( (iCUAddr == rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(iCUAddr))->getFirstCUAddr()) && // 1st in tile. (iCUAddr!=0) && (iCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr())/rpcPic->getNumPartInCU())) // !1st in frame && !1st in slice { if (pcSlice->getPPS()->getNumSubstreams() > 1) { // We're crossing into another tile, tiles are independent. // When tiles are independent, we have "substreams per tile". Each substream has already been terminated, and we no longer // have to perform it here. // For TILES_DECODER, there can be a header at the start of the 1st substream in a tile. These are read when the substreams // are extracted, not here. } else { #if CABAC_INIT_FLAG SliceType sliceType = pcSlice->getSliceType(); if (pcSlice->getCabacInitFlag()) { switch (sliceType) { case P_SLICE: // change initialization table to B_SLICE intialization sliceType = B_SLICE; break; case B_SLICE: // change initialization table to P_SLICE intialization sliceType = P_SLICE; break; default : // should not occur assert(0); } } m_pcEntropyDecoder->updateContextTables( sliceType, pcSlice->getSliceQp() ); #else m_pcEntropyDecoder->updateContextTables( pcSlice->getSliceType(), pcSlice->getSliceQp() ); #endif } Bool bTileMarkerFoundFlag = false; TComInputBitstream *pcTmpPtr; pcTmpPtr = ppcSubstreams[uiSubStrm]; // for CABAC for (UInt uiIdx=0; uiIdx<pcTmpPtr->getTileMarkerLocationCount(); uiIdx++) { if ( pcTmpPtr->getByteLocation() == (pcTmpPtr->getTileMarkerLocation( uiIdx )+2) ) { bTileMarkerFoundFlag = true; break; } } if (bTileMarkerFoundFlag) { UInt uiTileIdx; // Read tile index m_pcEntropyDecoder->readTileMarker( uiTileIdx, rpcPic->getPicSym()->getBitsUsedByTileIdx() ); } } #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif if ( pcSlice->getSPS()->getUseSAO() && pcSlice->getSaoInterleavingFlag() && pcSlice->getSaoEnabledFlag() ) { pcSlice->getAPS()->getSaoParam()->bSaoFlag[0] = pcSlice->getSaoEnabledFlag(); if (iCUAddr == iStartCUAddr) { pcSlice->getAPS()->getSaoParam()->bSaoFlag[1] = pcSlice->getSaoEnabledFlagCb(); pcSlice->getAPS()->getSaoParam()->bSaoFlag[2] = pcSlice->getSaoEnabledFlagCr(); } Int numCuInWidth = pcSlice->getAPS()->getSaoParam()->numCuInWidth; Int cuAddrInSlice = iCUAddr - pcSlice->getSliceCurStartCUAddr()/rpcPic->getNumPartInCU(); Int cuAddrUpInSlice = cuAddrInSlice - numCuInWidth; Int rx = iCUAddr % numCuInWidth; Int ry = iCUAddr / numCuInWidth; pcSbacDecoder->parseSaoOneLcuInterleaving(rx, ry, pcSlice->getAPS()->getSaoParam(),pcCU, cuAddrInSlice, cuAddrUpInSlice, pcSlice->getSPS()->getLFCrossSliceBoundaryFlag() ); } m_pcCuDecoder->decodeCU ( pcCU, uiIsLast ); m_pcCuDecoder->decompressCU ( pcCU ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif if( iSymbolMode ) { /*If at the end of a LCU line but not at the end of a substream, perform CABAC flush*/ if (!uiIsLast && pcSlice->getPPS()->getNumSubstreams() > 1) { if ((uiCol == uiTileLCUX+uiTileWidth-1) && (uiLin+iNumSubstreamsPerTile < uiTileLCUY+uiTileHeight)) { m_pcEntropyDecoder->decodeFlush(); } } pcSbacDecoders[uiSubStrm].load(pcSbacDecoder); //Store probabilities of second LCU in line into buffer if (pcSlice->getPPS()->getNumSubstreams() > 1 && (uiCol == uiTileLCUX+1)) { m_pcBufferSbacDecoders[uiTileCol].loadContexts( &pcSbacDecoders[uiSubStrm] ); } } } }