ErrVal MbDecoder::xDecodeMbIntra16x16( MbDataAccess& rcMbDataAccess, IntYuvMbBuffer& cYuvMbBuffer, IntYuvMbBuffer& rcPredBuffer ) { Int iStride = cYuvMbBuffer.getLStride(); RNOK( m_pcIntraPrediction->predictLumaMb( cYuvMbBuffer.getMbLumAddr(), iStride, rcMbDataAccess.getMbData().intraPredMode() ) ); rcPredBuffer.loadLuma( cYuvMbBuffer ); MbTransformCoeffs& rcCoeffs = m_cTCoeffs; Quantizer cQuantizer; cQuantizer.setQp ( rcMbDataAccess, false ); const QpParameter rcLQp = cQuantizer.getLumaQp(); Int iScaleY = g_aaiDequantCoef[rcLQp.rem()][0] << rcLQp.per(); const UChar* pucScaleY = rcMbDataAccess.getSH().getScalingMatrix( 0 ); if( pucScaleY ) { iScaleY *= pucScaleY[0]; iScaleY >>= 4; } RNOK( m_pcTransform->invTransformDcCoeff( rcCoeffs.get( B4x4Idx(0) ), iScaleY ) ); for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) { RNOK( m_pcTransform->invTransform4x4Blk( cYuvMbBuffer.getYBlk( cIdx ), iStride, rcCoeffs.get( cIdx ) ) ); } UInt uiChromaCbp = rcMbDataAccess.getMbData().getCbpChroma16x16(); RNOK( xDecodeChroma( rcMbDataAccess, cYuvMbBuffer, rcPredBuffer, uiChromaCbp, true ) ); return Err::m_nOK; }
ErrVal MbDecoder::xDecodeMbIntra4x4( MbDataAccess& rcMbDataAccess, IntYuvMbBuffer& cYuvMbBuffer, IntYuvMbBuffer& rcPredBuffer ) { Int iStride = cYuvMbBuffer.getLStride(); MbTransformCoeffs& rcCoeffs = m_cTCoeffs; for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) { rcMbDataAccess.getMbData().intraPredMode( cIdx ) = rcMbDataAccess.decodeIntraPredMode( cIdx ); XPel* puc = cYuvMbBuffer.getYBlk( cIdx ); UInt uiPredMode = rcMbDataAccess.getMbData().intraPredMode( cIdx ); RNOK( m_pcIntraPrediction->predictLumaBlock( puc, iStride, uiPredMode, cIdx ) ); rcPredBuffer.loadLuma( cYuvMbBuffer, cIdx ); if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx ) ) { RNOK( m_pcTransform->invTransform4x4Blk( puc, iStride, rcCoeffs.get( cIdx ) ) ); } } UInt uiChromaCbp = rcMbDataAccess.getMbData().getCbpChroma4x4(); RNOK( xDecodeChroma( rcMbDataAccess, cYuvMbBuffer, rcPredBuffer, uiChromaCbp, true ) ); return Err::m_nOK; }
Void MbTransformCoeffs::add( MbTransformCoeffs* pcCoeffs, Bool bLuma, Bool bChroma ) { if( bLuma ) { for( B4x4Idx bIdx; bIdx.isLegal(); bIdx++ ) { TCoeff* piCoeff = get( bIdx ); TCoeff* piSrcCoeff = pcCoeffs->get( bIdx ); for( UInt ui=0; ui<16; ui++ ) { piCoeff[ui]+= piSrcCoeff[ui]; } } } if( bChroma ) { for( CIdx cIdx; cIdx.isLegal(); cIdx++ ) { TCoeff* piCoeff = get( cIdx ); TCoeff* piSrcCoeff = pcCoeffs->get( cIdx ); for( UInt ui=0; ui<16; ui++ ) { piCoeff[ui] += piSrcCoeff[ui]; } } } }
Void MbTransformCoeffs::switchLevelCoeffData() { TCoeff sTemp; for( B4x4Idx bIdx; bIdx.isLegal(); bIdx++ ) { //TCoeff* piCoeff = m_aaiLevel[bIdx]; TCoeff* piCoeff = get( bIdx ); for( UInt ui=0; ui<16; ui++ ) { sTemp = piCoeff[ui].getLevel(); piCoeff[ui].setLevel( piCoeff[ui].getCoeff() ); piCoeff[ui].setCoeff( sTemp ); } } for( CIdx cIdx; cIdx.isLegal(); cIdx++ ) { //TCoeff* piCoeff = m_aaiLevel[cIdx]; TCoeff* piCoeff = get( cIdx ); for( UInt ui=0; ui<16; ui++ ) { sTemp = piCoeff[ui].getLevel(); piCoeff[ui].setLevel( piCoeff[ui].getCoeff() ); piCoeff[ui].setCoeff( sTemp ); } } }
ErrVal MbDecoder::xDecodeMbIntraBL( MbDataAccess& rcMbDataAccess, IntYuvPicBuffer* pcRecYuvBuffer, IntYuvMbBuffer& rcPredBuffer, IntYuvPicBuffer* pcBaseYuvBuffer ) { IntYuvMbBuffer cYuvMbBuffer; MbTransformCoeffs& rcCoeffs = m_cTCoeffs; cYuvMbBuffer.loadBuffer ( pcBaseYuvBuffer ); rcPredBuffer.loadLuma ( cYuvMbBuffer ); rcPredBuffer.loadChroma ( cYuvMbBuffer ); if( rcMbDataAccess.getMbData().isTransformSize8x8() ) { for( B8x8Idx cIdx; cIdx.isLegal(); cIdx++ ) { if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx ) ) { RNOK( m_pcTransform->invTransform8x8Blk( cYuvMbBuffer.getYBlk( cIdx ), cYuvMbBuffer.getLStride(), rcCoeffs.get8x8(cIdx) ) ); } } } else { for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) { if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx ) ) { RNOK( m_pcTransform->invTransform4x4Blk( cYuvMbBuffer.getYBlk( cIdx ), cYuvMbBuffer.getLStride(), rcCoeffs.get(cIdx) ) ); } } } UInt uiChromaCbp = rcMbDataAccess.getMbData().getCbpChroma4x4(); RNOK( xDecodeChroma( rcMbDataAccess, cYuvMbBuffer, rcPredBuffer, uiChromaCbp, false ) ); pcRecYuvBuffer->loadBuffer( &cYuvMbBuffer ); return Err::m_nOK; }
// functions for SVC to AVC rewrite JVT-V035 Void MbTransformCoeffs::storeLevelData() { for( B4x4Idx bIdx; bIdx.isLegal(); bIdx++ ) { //TCoeff* piCoeff = m_aaiLevel[bIdx]; TCoeff* piCoeff = get( bIdx ); for( UInt ui=0; ui<16; ui++ ) piCoeff[ui].setLevel( piCoeff[ui].getCoeff() ); } for( CIdx cIdx; cIdx.isLegal(); cIdx++ ) { //TCoeff* piCoeff = m_aaiLevel[cIdx]; TCoeff* piCoeff = get( cIdx ); for( UInt ui=0; ui<16; ui++ ) piCoeff[ui].setLevel( piCoeff[ui].getCoeff() ); } }
ErrVal SliceEncoder::xAddTCoeffs2( MbDataAccess& rcMbDataAccess, MbDataAccess& rcMbDataAccessBase ) { if( rcMbDataAccess.getMbData().isPCM() ) { TCoeff* pSrc = rcMbDataAccessBase.getMbTCoeffs().getTCoeffBuffer(); TCoeff* pDes = rcMbDataAccess .getMbTCoeffs().getTCoeffBuffer(); for( UInt ui = 0; ui < 384; ui++, pSrc++, pDes++ ) { ROT( pDes->getLevel() ); pDes->setLevel( pSrc->getLevel() ); } ROT( rcMbDataAccess.getMbData().getMbExtCbp() ); return Err::m_nOK; } UInt uiBCBP = 0; UInt uiCoded = 0; Bool bCoded = false; Bool bChromaAC = false; Bool bChromaDC = false; // Add the luma coefficients and track the new BCBP if( rcMbDataAccess.getMbData().isTransformSize8x8() ) { for( B8x8Idx c8x8Idx; c8x8Idx.isLegal(); c8x8Idx++ ) { bCoded = false; m_pcTransform->addPrediction8x8Blk( rcMbDataAccess.getMbTCoeffs().get8x8( c8x8Idx ), rcMbDataAccessBase.getMbTCoeffs().get8x8( c8x8Idx ), rcMbDataAccess.getMbData().getQp(), rcMbDataAccessBase.getMbData().getQp(), bCoded ); if( rcMbDataAccess.getMbData().isIntra16x16() ) AOT(1); if( bCoded ) uiBCBP |= (0x33 << c8x8Idx.b4x4()); } } else { for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) { uiCoded = 0; m_pcTransform->addPrediction4x4Blk( rcMbDataAccess.getMbTCoeffs().get( cIdx ), rcMbDataAccessBase.getMbTCoeffs().get( cIdx ), rcMbDataAccess.getMbData().getQp(), rcMbDataAccessBase.getMbData().getQp(), uiCoded ); if( rcMbDataAccess.getMbData().isIntra16x16() ) { if( *(rcMbDataAccess.getMbTCoeffs().get( cIdx )) ) uiCoded--; } if( uiCoded ) uiBCBP |= 1<<cIdx; } if( rcMbDataAccess.getMbData().isIntra16x16() ) { uiBCBP = uiBCBP?((1<<16)-1):0; } } // Add the chroma coefficients and update the BCBP m_pcTransform->addPredictionChromaBlocks( rcMbDataAccess.getMbTCoeffs().get( CIdx(0) ), rcMbDataAccessBase.getMbTCoeffs().get( CIdx(0) ), rcMbDataAccess.getSH().getCbQp( rcMbDataAccess.getMbData().getQp() ), rcMbDataAccess.getSH().getBaseSliceHeader()->getCbQp( rcMbDataAccessBase.getMbData().getQp() ), bChromaDC, bChromaAC ); m_pcTransform->addPredictionChromaBlocks( rcMbDataAccess.getMbTCoeffs().get( CIdx(4) ), rcMbDataAccessBase.getMbTCoeffs().get( CIdx(4) ), rcMbDataAccess.getSH().getCrQp( rcMbDataAccess.getMbData().getQp() ), rcMbDataAccess.getSH().getBaseSliceHeader()->getCrQp( rcMbDataAccessBase.getMbData().getQp() ), bChromaDC, bChromaAC ); uiBCBP |= (bChromaAC?2:(bChromaDC?1:0))<<16; // Update the CBP rcMbDataAccess.getMbData().setAndConvertMbExtCbp( uiBCBP ); // Update the Intra16x16 mode if( rcMbDataAccess.getMbData().isIntra16x16() ) { UInt uiMbType = INTRA_4X4 + 1; UInt uiPredMode = rcMbDataAccess.getMbData().intraPredMode(); UInt uiChromaCbp = uiBCBP>>16; Bool bACcoded = (uiBCBP && ((1<<16)-1)); uiMbType += uiPredMode; uiMbType += ( bACcoded ) ? 12 : 0; uiMbType += uiChromaCbp << 2; rcMbDataAccess.getMbData().setMbMode( MbMode(uiMbType) ); // Sanity checks if( rcMbDataAccess.getMbData().intraPredMode() != uiPredMode ) AOT(1); if( rcMbDataAccess.getMbData().getCbpChroma16x16() != uiChromaCbp ) AOT(1); if( rcMbDataAccess.getMbData().isAcCoded() != bACcoded ) AOT(1); }
// JVT-V035 ErrVal SliceEncoder::updatePictureAVCRewrite( ControlData& rcControlData, UInt uiMbInRow ) { ROF( m_bInitDone ); SliceHeader& rcSliceHeader = *rcControlData.getSliceHeader(); FMO& rcFMO = *rcSliceHeader.getFMO(); MbDataCtrl* pcMbDataCtrl = rcControlData.getMbDataCtrl(); MbDataCtrl* pcBaseLayerCtrl = rcControlData.getBaseLayerCtrl(); //====== initialization ====== RNOK( pcMbDataCtrl->initSlice( rcSliceHeader, DECODE_PROCESS, false, NULL ) ); if( rcSliceHeader.getTCoeffLevelPredictionFlag() == true ) { // Update the macroblock state // Must be done after the bit-stream has been constructed for( Int iSliceGroupId = rcFMO.getFirstSliceGroupId(); ! rcFMO.SliceGroupCompletelyCoded( iSliceGroupId ); iSliceGroupId = rcFMO.getNextSliceGroupId( iSliceGroupId ) ) { UInt uiFirstMbInSliceGroup = rcFMO.getFirstMBOfSliceGroup( iSliceGroupId ); UInt uiLastMbInSliceGroup = rcFMO.getLastMBInSliceGroup ( iSliceGroupId ); for( UInt uiMbAddress = uiFirstMbInSliceGroup; uiMbAddress <= uiLastMbInSliceGroup; uiMbAddress = rcFMO.getNextMBNr( uiMbAddress ) ) { UInt uiMbY = 0; UInt uiMbX = 0; MbDataAccess* pcMbDataAccess = 0; MbDataAccess* pcMbDataAccessBase = 0; rcSliceHeader.getMbPositionFromAddress( uiMbY, uiMbX, uiMbAddress ); RNOK( pcMbDataCtrl->initMb( pcMbDataAccess, uiMbY, uiMbX ) ); if( pcBaseLayerCtrl ) { RNOK( pcBaseLayerCtrl ->initMb( pcMbDataAccessBase, uiMbY, uiMbX ) ); pcMbDataAccess->setMbDataAccessBase( pcMbDataAccessBase ); } // modify QP values (as specified in G.8.1.5.1.2) if( pcMbDataAccess->getMbData().getMbCbp() == 0 && ( pcMbDataAccess->getMbData().getMbMode() == INTRA_BL || pcMbDataAccess->getMbData().getResidualPredFlag() ) ) { pcMbDataAccess->getMbData().setQp( pcMbDataAccessBase->getMbData().getQp() ); } if( pcMbDataAccess->isTCoeffPred() ) { if( pcMbDataAccess->getMbData().getMbMode() == INTRA_BL ) { // We're going to use the BL skip flag to correctly decode the intra prediction mode AOT( pcMbDataAccess->getMbData().getBLSkipFlag() == false ); // Inherit the mode of the base block pcMbDataAccess->getMbData().setMbMode( pcMbDataAccessBase->getMbData().getMbMode() ); // Inherit intra prediction modes for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) pcMbDataAccess->getMbData().intraPredMode(cIdx) = pcMbDataAccessBase->getMbData().intraPredMode(cIdx); pcMbDataAccess->getMbData().setChromaPredMode( pcMbDataAccessBase->getMbData().getChromaPredMode() ); } // The 8x8 transform flag is present in the bit-stream unless transform coefficients // are not transmitted at the enhancement layer. In this case, inherit the base layer // transform type. This makes intra predition work correctly, etc. if( ( pcMbDataAccess->getMbData().getMbCbp() & 0x0F ) == 0 ) { pcMbDataAccess->getMbData().setTransformSize8x8( pcMbDataAccessBase->getMbData().isTransformSize8x8() ); } xAddTCoeffs2( *pcMbDataAccess, *pcMbDataAccessBase ); } if( pcMbDataAccess->getMbAddress() != uiFirstMbInSliceGroup && pcMbDataAccess->getSH().getTCoeffLevelPredictionFlag() && !pcMbDataAccess->getSH().getNoInterLayerPredFlag() && !pcMbDataAccess->getMbData().isIntra16x16() && pcMbDataAccess->getMbData().getMbExtCbp() == 0 ) { pcMbDataAccess->getMbData().setQp4LF( pcMbDataAccess->getLastQp4LF() ); } else { pcMbDataAccess->getMbData().setQp4LF( pcMbDataAccess->getMbData().getQp() ); } } } } return Err::m_nOK; }
ErrVal MbDecoder::xDecodeMbInter( MbDataAccess& rcMbDataAccess, MbDataAccess* pcMbDataAccessBase, IntYuvMbBuffer& rcPredBuffer, IntYuvPicBuffer* pcRecYuvBuffer, IntFrame* pcResidual, IntFrame* pcBaseResidual, RefFrameList& rcRefFrameList0, RefFrameList& rcRefFrameList1, Bool bReconstruct ) { IntYuvMbBuffer cYuvMbBuffer; cYuvMbBuffer .setAllSamplesToZero(); IntYuvMbBuffer cYuvMbBufferResidual; cYuvMbBufferResidual.setAllSamplesToZero(); MbTransformCoeffs& rcCoeffs = m_cTCoeffs; Bool bCalcMv = false; Bool bFaultTolerant = true; //===== derive motion vectors ===== calcMv( rcMbDataAccess, pcMbDataAccessBase ); //===== get prediction signal when full reconstruction is requested ===== if( bReconstruct ) { if( rcMbDataAccess.getMbData().getMbMode() == MODE_8x8 || rcMbDataAccess.getMbData().getMbMode() == MODE_8x8ref0 ) { for( B8x8Idx c8x8Idx; c8x8Idx.isLegal(); c8x8Idx++ ) { //----- motion compensated prediction ----- RNOK( m_pcMotionCompensation->compensateSubMb ( c8x8Idx, rcMbDataAccess, rcRefFrameList0, rcRefFrameList1, &cYuvMbBuffer, bCalcMv, bFaultTolerant ) ); } } else { //----- motion compensated prediction ----- RNOK( m_pcMotionCompensation->compensateMb ( rcMbDataAccess, rcRefFrameList0, rcRefFrameList1, &cYuvMbBuffer, bCalcMv ) ); } rcPredBuffer.loadLuma ( cYuvMbBuffer ); rcPredBuffer.loadChroma ( cYuvMbBuffer ); } //===== reconstruct residual signal by using transform coefficients ====== m_pcTransform->setClipMode( false ); if( rcMbDataAccess.getMbData().isTransformSize8x8() ) { for( B8x8Idx cIdx; cIdx.isLegal(); cIdx++ ) { if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx ) ) { RNOK( m_pcTransform->invTransform8x8Blk( cYuvMbBufferResidual.getYBlk( cIdx ), cYuvMbBufferResidual.getLStride(), rcCoeffs.get8x8(cIdx) ) ); } } } else { for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) { if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx ) ) { RNOK( m_pcTransform->invTransform4x4Blk( cYuvMbBufferResidual.getYBlk( cIdx ), cYuvMbBufferResidual.getLStride(), rcCoeffs.get(cIdx) ) ); } } } UInt uiChromaCbp = rcMbDataAccess.getMbData().getCbpChroma4x4(); RNOK( xDecodeChroma( rcMbDataAccess, cYuvMbBufferResidual, rcPredBuffer, uiChromaCbp, false ) ); m_pcTransform->setClipMode( true ); //===== add base layer residual ===== if( rcMbDataAccess.getMbData().getResidualPredFlag( PART_16x16 ) ) { IntYuvMbBuffer cBaseLayerBuffer; cBaseLayerBuffer.loadBuffer( pcBaseResidual->getFullPelYuvBuffer() ); //-- JVT-R091 if ( bReconstruct && rcMbDataAccess.getMbData().getSmoothedRefFlag() ) { IntYuvMbBuffer cMbBuffer; // obtain P cMbBuffer.loadLuma ( cYuvMbBuffer ); cMbBuffer.loadChroma( cYuvMbBuffer ); // P+Rb cMbBuffer.add( cBaseLayerBuffer ); // S(P+Rb) pcRecYuvBuffer->loadBuffer( &cMbBuffer ); pcRecYuvBuffer->smoothMbInside(); if ( rcMbDataAccess.isAboveMbExisting() ) { pcRecYuvBuffer->smoothMbTop(); } if ( rcMbDataAccess.isLeftMbExisting() ) { pcRecYuvBuffer->smoothMbLeft(); } // store new prediction cYuvMbBuffer.loadBuffer ( pcRecYuvBuffer ); cYuvMbBuffer.subtract ( cBaseLayerBuffer ); // update rcPredBuffer rcPredBuffer.loadLuma ( cYuvMbBuffer ); rcPredBuffer.loadChroma ( cYuvMbBuffer ); } //-- cYuvMbBufferResidual.add( cBaseLayerBuffer ); //--- set CBP --- rcMbDataAccess.getMbData().setMbExtCbp( rcMbDataAccess.getMbData().getMbExtCbp() | pcMbDataAccessBase->getMbData().getMbExtCbp() ); } //===== reconstruct signal ===== if( bReconstruct ) { cYuvMbBuffer.add( cYuvMbBufferResidual ); cYuvMbBuffer.clip(); } //===== store reconstructed residual ===== if( pcResidual ) { RNOK( pcResidual->getFullPelYuvBuffer()->loadBuffer( &cYuvMbBufferResidual ) ); } //===== store reconstructed signal ===== if( pcRecYuvBuffer ) { RNOK( pcRecYuvBuffer->loadBuffer( &cYuvMbBuffer ) ); } return Err::m_nOK; }
ErrVal MbDecoder::xDecodeMbInter( MbDataAccess& rcMbDataAccess, YuvMbBuffer& rcRecYuvBuffer, IntYuvMbBuffer& rcPredIntYuvMbBuffer, IntYuvMbBuffer& rcResIntYuvMbBuffer, Bool bReconstruct ) { rcResIntYuvMbBuffer.setAllSamplesToZero(); if( ! bReconstruct ) { RNOK( m_pcMotionCompensation->calculateMb ( rcMbDataAccess, true ) ); rcRecYuvBuffer.setZero(); } else { RNOK( m_pcMotionCompensation->compensateMb( rcMbDataAccess, &rcRecYuvBuffer, true ) ); } rcPredIntYuvMbBuffer.loadBuffer( &rcRecYuvBuffer ); MbTransformCoeffs& rcCoeffs = m_cTCoeffs; m_pcTransform->setClipMode( false ); if( rcMbDataAccess.getMbData().isTransformSize8x8() ) { for( B8x8Idx cIdx8x8; cIdx8x8.isLegal(); cIdx8x8++ ) { if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx8x8 ) ) { RNOK( m_pcTransform->invTransform8x8Blk( rcResIntYuvMbBuffer.getYBlk( cIdx8x8 ), rcResIntYuvMbBuffer.getLStride(), rcCoeffs.get8x8(cIdx8x8) ) ); } } } else { for( B4x4Idx cIdx; cIdx.isLegal(); cIdx++ ) { if( rcMbDataAccess.getMbData().is4x4BlkCoded( cIdx ) ) { RNOK( m_pcTransform->invTransform4x4Blk( rcResIntYuvMbBuffer.getYBlk( cIdx ), rcResIntYuvMbBuffer.getLStride(), rcCoeffs.get(cIdx) ) ); } } } UInt uiChromaCbp = rcMbDataAccess.getMbData().getCbpChroma4x4(); IntYuvMbBuffer cPredBuffer; RNOK( xDecodeChroma( rcMbDataAccess, rcResIntYuvMbBuffer, cPredBuffer, uiChromaCbp, false ) ); m_pcTransform->setClipMode( true ); IntYuvMbBuffer cIntYuvMbBuffer; cIntYuvMbBuffer. loadLuma ( rcPredIntYuvMbBuffer ); cIntYuvMbBuffer. loadChroma ( rcPredIntYuvMbBuffer ); cIntYuvMbBuffer. add ( rcResIntYuvMbBuffer ); rcRecYuvBuffer. loadBufferClip( &cIntYuvMbBuffer ); return Err::m_nOK; }