📄 umc_h264_ermb.cpp
字号:
//// INTEL CORPORATION PROPRIETARY INFORMATION// This software is supplied under the terms of a license agreement or// nondisclosure agreement with Intel Corporation and may not be copied// or disclosed except in accordance with the terms of that agreement.// Copyright (c) 2004 - 2005 Intel Corporation. All Rights Reserved.//#include "umc_h264_video_encoder.h"#include "umc_h264_tables.h"#include "umc_h264_bme.h"#include "ippdefs.h"Ipp32s dec_single_scan[2][16] = { {0,1,4,8,5,2,3,6,9,12,13,10,7,11,14,15}, {0,4,1,8,12,5,9,13,2,6,10,14,3,7,11,15}};Ipp32s dec_single_scan_p[4] = {0,1,2,3};Ipp16s enc_single_scan[2][16] = { {0,1,5,6,2,4,7,12,3,8,11,13,9,10,14,15}, {0,1,4,8,5,2,3,6,9,12,13,10,7,11,14,15}};////////////////////////////////////////////////////////////////////////////////// CEncAndRec4x4IntraMB//// Encode and Reconstruct all blocks in one Intra macroblock with 4x4 prediction//using namespace UMC_H264_ENCODER;////////////////////////////////////////////////////////////////////////////////namespace UMC{Ipp32u H264VideoEncoder::CEncAndRec4x4IntraMB(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* pMassDiffBuf; // difference block pointer Ipp16s* pTempDiffBuf; // difference block pointer Ipp16s* pDCBuf; // chroma & luma dc coeffs pointer Ipp8u* pPredBuf; // prediction block pointer Ipp16s* pDiffBuf; // 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 Ipp32s iMBCost; // recode MB cost counter Ipp32s iBlkCost[2]; // coef removal counter for left/right 8x8 luma blocks Ipp8u bCoded; // coded block flag T_4x4IntraModeSelParams ModeSelParams; // for 4x4 intra block function 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;#ifdef _INTRA_MODE_SWITCH_ Ipp32u SaveIntraPred[4];#endif 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; iMBCost = 0; iBlkCost[0] = 0; iBlkCost[1] = 0;#ifdef _INTRA_MODE_SWITCH_ // Four 32 bit values (16 pels) are saved from the prediction buffer so that they can be restored // in the event that this MB gets recoded as 16x16 Intra. The Pred buffer currently contains the // best 16x16 Intra mode prediciton, and this function only changes the upper 4x4 block SaveIntraPred[0] = *((Ipp32u*)pPredBuf); SaveIntraPred[1] = *((Ipp32u*)(pPredBuf+16)); SaveIntraPred[2] = *((Ipp32u*)(pPredBuf+32)); SaveIntraPred[3] = *((Ipp32u*)(pPredBuf+48));#endif //-------------------------------------------------------------------------- // 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; // get AI/MV array index for first block of the MB uIndex = m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex; // MB level init for 4x4 intra mode select Intra4x4InitBlockParams(&ModeSelParams, uMB); // 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; // These 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 = 16; } // find advanced intra prediction block, store in PredBuf // Select best AI mode for the block, using reconstructed // predictor pels. This function also stores the block // predictor pels at pPredBuf. uIntraSAD += AIModeSelectOneBlock( &ModeSelParams, pSrcPlane + uOffset, pRecPlane + uOffset, uBlock, &m_pCurrentFrame->pAIMode[uIndex], pPredBuf); // 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 use 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 use pDiffBuf // input and output are being passed in the mmx reg.s // quantization and dequantization // note: asm version does not use pDiffBuf and pDQBuf // these values are being passed in the mmx registers ippiTransformQuantResidual_H264_16s_C1I (pDiffBuf,uMBQP,&iNumCoeffs,(m_SliceHeader.slice_type == INTRASLICE), enc_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE],&uLastCoeff); // 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)ABS(iNumCoeffs); if (m_PicParamSet.entropy_coding_mode) { int ctxIdxBlockCat = BLOCK_LUMA_LEVELS; ScanSignificant_CABAC(pDiffBuf,ctxIdxBlockCat,16, dec_single_scan[m_PicParamSet.picture_structure != FRAME_PICTURE], &m_pCurrentFrame->Block_CABAC[uBlock]); bCoded = m_pCurrentFrame->Block_CABAC[uBlock].uNumSigCoeffs; } else { // record RLE info ippiEncodeCoeffsCAVLC_H264_16s ( pDiffBuf, 0, 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; } //bCoded = RLE( // pDiffBuf, // quantized coeffs in scan order // 16, // 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]; // 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, pDiffBuf, NULL, pRecPlane + uOffset, 16, uPitch, uMBQP, ((iNumCoeffs < -1) || (iNumCoeffs > 0))); } } // block not declared empty // proceed to the next block uIndex += m_EncBlockIndexInc[uBlock]; uOffset += m_EncBlockOffsetInc[uBlock]; uBlock ++; } // for uBlock in luma plane // Check if this block should be coded with a different mode if (m_SliceHeader.slice_type != INTRASLICE) { if (uIntraSAD >= m_uMBInterSAD) { // INTER is better, recode the MB as INTER m_pCurrentFrame->pMBData[uMB].uMBType = m_uInterMBType; m_pCurrentFrame->pMBData[uMB].uCBP4x4 = m_uInterCBP4x4; m_Intra_MB_Counter --; // Fixup the Intra 4x4 mode buffer uIndex = m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex; for (uBlock = 0; uBlock < 16; uBlock++) { m_pCurrentFrame->pAIMode[uIndex] = (T_AIMode) 2; uIndex += m_EncBlockIndexInc[uBlock]; } return 0; // Bail and recode as Inter... } }#ifdef _INTRA_MODE_SWITCH_ // Always consider recoding as Intra 16x16, regardless of slice type. if (uIntraSAD >= m_uMBIntra16x16SAD) { // INTER is better, recode the MB as INTER m_pCurrentFrame->pMBData[uMB].uMBType = (Ipp8u) MBTYPE_INTRA_16x16; m_pCurrentFrame->pMBData[uMB].uCBP4x4 = 0xffffff; // Fixup the Intra 4x4 mode buffer uIndex = m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex; for (uBlock = 0; uBlock < 16; uBlock++) { m_pCurrentFrame->pAIMode[uIndex] = (T_AIMode) 2; uIndex += m_EncBlockIndexInc[uBlock]; } // Restore the four 32 bit values (16 pels) that were saved from the prediction buffer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -