📄 umc_h264_ermb.cpp
字号:
Ipp32u H264VideoEncoder::CEncAndRec16x16IntraMB(Ipp32u uMB){ Ipp32u uBlock; // block number, 0 to 23 Ipp32u uIndex; // block-dependent, into AI and MV arrays Ipp32u uOffset; // to upper left corner of block from start of plane Ipp32u uMBQP; // QP of current MB Ipp32u uMBType; // current MB type Ipp8u uMBEdgeType; // current MB edge type Ipp32u uCBP4x4; // coded flags for all 4x4 blocks Ipp32u uIntraSAD; // intra MB SAD Ipp16s* pDCBuf; // chroma & luma dc coeffs pointer Ipp8u* pPredBuf; // prediction block pointer Ipp16s* pDiffBuf; // difference block pointer Ipp16s* pTempDiffBuf; // difference block pointer Ipp16s* pMassDiffBuf; // difference block pointer Ipp16s* pQBuf; // quantized block pointer// Ipp16s* pDQBuf; // dequantized block pointer Ipp8u* pSrcPlane; // start of plane to encode Ipp8u* pRecPlane; // start of reconstructed plane Ipp32u uPitch; // buffer pitch Ipp8u bCoded; // coded block flag T_NumCoeffs iNumCoeffs; // Number of nonzero coeffs after quant (negative if DC is nonzero) Ipp8u uLastCoeff; // Number of nonzero coeffs after quant (negative if DC is nonzero) Ipp32u RLE_Offset; // Index into BlockRLE array Ipp32u rc; uPitch = m_pCurrentFrame->uPitch; uCBP4x4 = m_pCurrentFrame->pMBData[uMB].uCBP4x4; uMBQP = m_pCurrentFrame->pMBData[uMB].uMBQP; uMBType = m_pCurrentFrame->pMBData[uMB].uMBType; uMBEdgeType = m_pCurrentFrame->pMBData[uMB].uEdgeType; pPredBuf = m_pCurrentFrame->pMBEncodeBuffer; // 16-byte aligned work buffer pDiffBuf = (Ipp16s*) (pPredBuf + 512); pQBuf = (Ipp16s*) (pDiffBuf + 16);// pDQBuf = (Ipp16s*) (pQBuf + 16); pDCBuf = (Ipp16s*) (pQBuf + 16); // Used for both luma and chroma DC blocks pMassDiffBuf = (Ipp16s*) (pDCBuf + 16);// uIntraSAD = rd_quant_intra[uMBQP] * 24; // 'handicap' using reconstructed data uIntraSAD = 0; //-------------------------------------------------------------------------- // encode Y plane blocks (0-15) //-------------------------------------------------------------------------- // initialize pointers and offset pSrcPlane = m_pCurrentFrame->m_pYPlane; pRecPlane = m_pReconstructFrame->m_pYPlane; uOffset = m_pCurrentFrame->pMBOffsets[uMB].uLumaOffset + m_pCurrentFrame->y_line_shift; RLE_Offset = Y_DC_RLE; // Used in 16x16 Intra mode only // get AI/MV array index for first block of the MB uIndex = m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex; // for INTRA 16x16 MBs computation of luma prediction was done as // a byproduct of sad calculation prior to this function being // called; the predictor blocks are already at pPredBuf. // Initialize the AC coeff flag value m_pCurrentFrame->pMBData[uMB].uLumaAC = 0; // compute the 4x4 luma DC transform coeffs ippiSumsDiff16x16Blocks4x4_8u16s_C1( pSrcPlane + uOffset, uPitch, pPredBuf, 16, pDCBuf, pMassDiffBuf); // apply second transform on the luma DC transform coeffs rc = ippiTransformQuantLumaDC_H264_16s_C1I(pDCBuf,pQBuf,uMBQP,&iNumCoeffs,1, enc_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE],&uLastCoeff); // If rc != 0, then a quantized level was out of range for coding // with CAVLC, and this MB must be quantized more (or coded a different way) while (rc) { // Right now, we quantize more until all of the levels are OK uMBQP = ++m_pCurrentFrame->pMBData[uMB].uMBQP; // Increase by a level rc = ippiTransformQuantLumaDC_H264_16s_C1I(pDCBuf,pQBuf,uMBQP,&iNumCoeffs,0, enc_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE],&uLastCoeff); } m_pCurrentFrame->pMBData[uMB].DC16x16Coeffs = ABS(iNumCoeffs); // insert the quantized luma double transform DC coeffs into // RLE buffer // record RLE info if (m_PicParamSet.entropy_coding_mode) { int ctxIdxBlockCat = BLOCK_LUMA_DC_LEVELS; ScanSignificant_CABAC(pDCBuf,ctxIdxBlockCat,16, dec_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE], &m_pCurrentFrame->Block_CABAC[RLE_Offset]); bCoded = m_pCurrentFrame->Block_CABAC[RLE_Offset].uNumSigCoeffs; } else { ippiEncodeCoeffsCAVLC_H264_16s ( pDCBuf, 0, dec_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE], uLastCoeff, &m_pCurrentFrame->Block_RLE[RLE_Offset].uTrailing_Ones, &m_pCurrentFrame->Block_RLE[RLE_Offset].uTrailing_One_Signs, &m_pCurrentFrame->Block_RLE[RLE_Offset].uNumCoeffs, &m_pCurrentFrame->Block_RLE[RLE_Offset].uTotalZeros, m_pCurrentFrame->Block_RLE[RLE_Offset].iLevels, m_pCurrentFrame->Block_RLE[RLE_Offset].uRuns); bCoded = m_pCurrentFrame->Block_RLE[RLE_Offset].uNumCoeffs; } //bCoded = RLE( // pDCBuf, // quantized coeffs in scan order // 16, // number of coeffs // &m_pCurrentFrame->Block_RLE[RLE_Offset] // where to put RLE data // ); ippiTransformDequantLumaDC_H264_16s_C1I (pDCBuf, uMBQP); // loop over all 4x4 blocks in Y plane for the MB for (uBlock = 0; uBlock < 16; ) { pPredBuf = m_pCurrentFrame->pMBEncodeBuffer + xoff[uBlock] + yoff[uBlock]*16; m_pCurrentFrame->pYNumCoeffs[uIndex] = 0; // This will be updated if the block is coded if (m_PicParamSet.entropy_coding_mode) { m_pCurrentFrame->Block_CABAC[uBlock].uNumSigCoeffs = 0; } else { m_pCurrentFrame->Block_RLE[uBlock].uNumCoeffs = 0; m_pCurrentFrame->Block_RLE[uBlock].uTrailing_Ones = 0; m_pCurrentFrame->Block_RLE[uBlock].uTrailing_One_Signs = 0; m_pCurrentFrame->Block_RLE[uBlock].uTotalZeros = 15; } // check if block is coded bCoded = ((uCBP4x4 & CBP4x4Mask[uBlock])?(1):(0)); if (!bCoded) { // update reconstruct frame for the empty block Copy4x4( pPredBuf, // predictor block uPitch, pRecPlane + uOffset); // reconstruct frame } else { // block not declared empty, encode // compute difference of predictor and source pels // note: asm version does not used pDiffBuf // output is being passed in the mmx registers /* Diff4x4( pPredBuf, // predictor pels pSrcPlane + uOffset, // source pels uPitch, // source pitch pDiffBuf); // result buffer // forward transform, in place in iDiffBuf // note: asm version does not used pDiffBuf // input and output are being passed in the mmx reg.s ippiQuantTransformResidual_H264_16s_C1I(pDiffBuf,uMBQP,&iNumCoeffs,&uLastCoeff,(m_SliceHeader.slice_type == INTRASLICE)); */ // linear formula pTempDiffBuf = pMassDiffBuf+ uBlock*16; or pTempDiffBuf = pMassDiffBuf+ (uBlock/4)*64+(uBlock%4)*16; pTempDiffBuf = pMassDiffBuf+ xoff[uBlock]*4 + yoff[uBlock]*16; ippiTransformQuantResidual_H264_16s_C1I (pTempDiffBuf,uMBQP,&iNumCoeffs,(m_SliceHeader.slice_type == INTRASLICE), enc_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE],&uLastCoeff); // restore luma DC transform coeff if 16x16 intra mode // Also, saves the value of iNonEmpty for later use // TBD: Maybe this should be part of QDQ or RLE? m_pCurrentFrame->pMBData[uMB].uLumaAC |= ((iNumCoeffs < -1) || (iNumCoeffs > 0)); //pDQBuf[0] = pDCBuf[block_subblock_mapping[uBlock]]; // if everything quantized to zero, skip RLE if (!iNumCoeffs) { // the block is empty so it is not coded bCoded = 0; } else { // Preserve the absolute number of coeffs. m_pCurrentFrame->pYNumCoeffs[uIndex] = (T_NumCoeffs)((iNumCoeffs < 0) ? -(iNumCoeffs+1) : iNumCoeffs); if (m_PicParamSet.entropy_coding_mode) { int ctxIdxBlockCat = BLOCK_LUMA_AC_LEVELS; ScanSignificant_CABAC(pTempDiffBuf,ctxIdxBlockCat,15, dec_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE], &m_pCurrentFrame->Block_CABAC[uBlock]); bCoded = m_pCurrentFrame->Block_CABAC[uBlock].uNumSigCoeffs; } else { ippiEncodeCoeffsCAVLC_H264_16s ( pTempDiffBuf,//pDiffBuf, 1, dec_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE], uLastCoeff, &m_pCurrentFrame->Block_RLE[uBlock].uTrailing_Ones, &m_pCurrentFrame->Block_RLE[uBlock].uTrailing_One_Signs, &m_pCurrentFrame->Block_RLE[uBlock].uNumCoeffs, &m_pCurrentFrame->Block_RLE[uBlock].uTotalZeros, m_pCurrentFrame->Block_RLE[uBlock].iLevels, m_pCurrentFrame->Block_RLE[uBlock].uRuns); m_pCurrentFrame->pYNumCoeffs[uIndex] = bCoded = m_pCurrentFrame->Block_RLE[uBlock].uNumCoeffs; } // record RLE info //bCoded = RLE( // pDiffBuf, // quantized coeffs in scan order // 15, // number of coeffs // &m_pCurrentFrame->Block_RLE[uBlock] // where to put RLE data // ); } // update flags if block quantized to empty if (!bCoded) uCBP4x4 &= ~CBP4x4Mask[uBlock]; // If the block wasn't coded and the DC coefficient is zero if (!bCoded && !pDCBuf[block_subblock_mapping[uBlock]]) { // update reconstruct frame for the empty block Copy4x4( pPredBuf, // predictor block uPitch, pRecPlane + uOffset); // reconstruct frame } else { // inverse transform for reconstruct AND... // add inverse transformed coefficients to original predictor // to obtain reconstructed block, store in reconstruct frame // buffer ippiDequantTransformResidualAndAdd_H264_16s_C1I ( pPredBuf, pTempDiffBuf,//pDiffBuf, &pDCBuf[block_subblock_mapping[uBlock]], pRecPlane + uOffset, 16, uPitch, uMBQP, ((iNumCoeffs < -1) || (iNumCoeffs > 0))); } } // block not declared empty // proceed to the next block uOffset += m_EncBlockOffsetInc[uBlock]; uIndex += m_EncBlockIndexInc[uBlock]; uBlock ++; } // for uBlock in luma plane //-------------------------------------------------------------------------- // encode U plane blocks (16-19) then V plane blocks (20-23) //-------------------------------------------------------------------------- // In JVT, Chroma is Intra if any part of luma is intra. m_pCurrentFrame->pMBData[uMB].uChromaNC = 0; uOffset = m_pCurrentFrame->pMBOffsets[uMB].uChromaOffset + m_pCurrentFrame->uv_line_shift; int left = m_pCurrentFrame->uMBxpos > 0; // shows whether pixels are available to the left of the MB. int top = m_pCurrentFrame->uMBypos > 0; // shows whether pixels are available above the MB. int available = (top<<1)|left; // Because JVT jointly codes the Intra prediction type for both // U and V MBs (they use the same type), we need to jointly determine // the best type, and save the predictor values for both in the // pPredBuf to be used below. This is OK, since this is typically used // as a 16x16 buffer and the U and V predictions are each 8x8 blocks. // The 8x8 blocks are stored U above V, and the buffer pitch is 16. AIModeSelectChromaMBs_8x8( m_pCurrentFrame->m_pUPlane + uOffset, m_pReconstructFrame->m_pUPlane + uOffset, m_pCurrentFrame->m_pVPlane + uOffset, m_pReconstructFrame->m_pVPlane + uOffset, uPitch, uMBEdgeType, available, &m_pCurrentFrame->pMBData[uMB].uChromaType,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -