📄 umc_h264_aic.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 - 2007 Intel Corporation. All Rights Reserved.
//
#include <string.h>
#include "vm_debug.h"
#include "umc_h264_video_encoder.h"
#include "umc_h264_tables.h"
#include "umc_h264_bme.h"
////////////////////////////////////////////////////////////////////////////////
// Intra4x4InitBlockParams
//
// Sets up the parameters for the 4x4 block level mode select function. Must
// be called once per MB prior to calling the mode select function.
//
////////////////////////////////////////////////////////////////////////////////
// Uncomment the following #define to remove the left MB dependency in the
// code to select the 4x4 Intra mode for a given block.
//#define NOINTRALEFTDEP
// 4x4 Prediction Details
// The predictors for the 16 pels of a 4x4 block are obtained using pels
// above and to the left of the block, used dependent upon prediction mode.
//
// Notation for comments regarding prediction and predictors.
// The pels of the 4x4 block are labelled a..p. The predictor pels above
// are labelled A..H, from the left I..L, and from above left M, as follows:
//
// M A B C D E F G H
// I a b c d
// J e f g h
// K i j k l
// L m n o p
// Predictor array index definitions
#define P_Z PredPel[0]
#define P_A PredPel[1]
#define P_B PredPel[2]
#define P_C PredPel[3]
#define P_D PredPel[4]
#define P_E PredPel[5]
#define P_F PredPel[6]
#define P_G PredPel[7]
#define P_H PredPel[8]
#define P_I PredPel[9]
#define P_J PredPel[10]
#define P_K PredPel[11]
#define P_L PredPel[12]
#define P_M (PredPel[13])
#define P_N (PredPel[14])
#define P_O (PredPel[15])
#define P_P (PredPel[16])
#define P_Q (PredPel[17])
#define P_R (PredPel[18])
#define P_S (PredPel[19])
#define P_T (PredPel[20])
#define P_U (PredPel[21])
#define P_V (PredPel[22])
#define P_W (PredPel[23])
#define P_X (PredPel[24])
// Predicted pixel array offset macros
#define P_a pPredBuf[0]
#define P_b pPredBuf[1]
#define P_c pPredBuf[2]
#define P_d pPredBuf[3]
#define P_e pPredBuf[0+1*16]
#define P_f pPredBuf[1+1*16]
#define P_g pPredBuf[2+1*16]
#define P_h pPredBuf[3+1*16]
#define P_i pPredBuf[0+2*16]
#define P_j pPredBuf[1+2*16]
#define P_k pPredBuf[2+2*16]
#define P_l pPredBuf[3+2*16]
#define P_m pPredBuf[0+3*16]
#define P_n pPredBuf[1+3*16]
#define P_o pPredBuf[2+3*16]
#define P_p pPredBuf[3+3*16]
namespace UMC_H264_ENCODER
{
#define NUM_AI_MODES 9
Ipp32s intra_modes[4][8] = {
{0,1,3,7,8,-1,-1,-1},
{0,1,3,4,5, 6, 7, 8},
{0,3,7,-1,-1,-1,-1,-1},
{1,8,-1,-1,-1,-1,-1,-1}
};
////////////////////////////////////////////////////////////////////////////////
// AdvancedIntraModeSelectOneMacroblock
//
// Main function to drive advanced intra mode select for one macroblock.
////////////////////////////////////////////////////////////////////////////////
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::AdvancedIntraModeSelectOneMacroblock(
H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice,
Ipp32u uMB, // which MB
Ipp32u uBestSAD,
Ipp32u *puAIMBSAD // return total MB SAD here
)
{
H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
// All 9 intra modes are checked. Since we treat all 4x4 blocks before
// coding/decoding the prediction may not be based on decoded pixels (except
// for some of the blocks). Therefore original pixel data are used for
// prediction in this assessment of intra coding. This will result in
// too good prediction.
// To compensate for this the SAD for intra is given a 'handicap'
// depending on QP. Notice: Original data is used for prediction only
// in mode selection. When real coding is performed, prediction is made
// from decoded data
//Ipp32u uMBQP = curr_slice->m_cur_mb.LocalMacroblockInfo->QP;
*puAIMBSAD = 0;//rd_quant_intra[uMBQP]; //TODO ADB
// pointer to upper left pel of first block
PixType *pBlock = cur_mb.mbPtr;
PixType *rBlock = m_pReconstructFrame->m_pYPlane + m_pMBOffsets[uMB].uLumaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field];
Ipp32s uBlock;
if( m_Analyse & ANALYSE_RD_OPT ){
curr_slice->fakeBitstream->CopyContext_CABAC(*(curr_slice->m_pbitstream));
curr_slice->fakeBitstream->SaveContext_CABAC();
}
// loop over all 16 4x4 blocks in the MB
for (uBlock = 0; uBlock < 16; uBlock++){
PixType *pPredBuf = 0;
if (curr_slice->m_use_transform_for_intra_decision)
pPredBuf = cur_mb.mb4x4.prediction + xoff[uBlock] + yoff[uBlock]*16;
if( m_Analyse & ANALYSE_RD_OPT && pPredBuf ){
*puAIMBSAD += Intra4x4SelectRD(curr_slice,
pBlock, // source block
rBlock, // no reference block yet, use source for ref.
uBlock,
curr_slice->m_cur_mb.intra_types,
pPredBuf);
}else{
// CPU-dependent call to block level mode select
*puAIMBSAD += AIModeSelectOneBlock(curr_slice,
pBlock, // source block
rBlock, // no reference block yet, use source for ref.
uBlock,
curr_slice->m_cur_mb.intra_types,
pPredBuf); // no return of predictor pels
}
#ifndef H264_RD_OPT
if( *puAIMBSAD > uBestSAD ){
return; //Don't count anymore because previous SAD is better.
}
#endif
// next block
pBlock += m_EncBlockOffsetInc[curr_slice->m_is_cur_mb_field][uBlock];
rBlock += m_EncBlockOffsetInc[curr_slice->m_is_cur_mb_field][uBlock];
}
if (((m_Analyse & ANALYSE_RD_OPT) && (curr_slice->m_slice_type != INTRASLICE)) || (!(m_Analyse & ANALYSE_RD_OPT) && (m_Analyse & ANALYSE_RD_MODE))) {
// for ANALYSE_RD_OPT it is need to calc Chroma for non INTRA slices
CH264pBs<PixType,CoeffsType> *pBitstream = curr_slice->m_pbitstream;
curr_slice->fakeBitstream->Reset();
curr_slice->fakeBitstream->CopyContext_CABAC(*pBitstream);
Ipp32s ob = curr_slice->fakeBitstream->m_nOutstandingBits;
curr_slice->m_pbitstream = curr_slice->fakeBitstream;
H264MacroblockLocalInfo sLocalMBinfo = *cur_mb.LocalMacroblockInfo;
H264MacroblockGlobalInfo sGlobalMBinfo = *cur_mb.GlobalMacroblockInfo;
pSetMB8x8TSPackFlag(cur_mb.GlobalMacroblockInfo, false);
cur_mb.GlobalMacroblockInfo->mbtype = MBTYPE_INTRA;
cur_mb.LocalMacroblockInfo->cbp_luma = curr_slice->m_uIntraCBP4x4;
CEncAndRec4x4IntraMB(curr_slice);
if (m_PicParamSet.chroma_format_idc)
EncodeChroma(curr_slice);
Put_MB(curr_slice);
Ipp32s bs = curr_slice->fakeBitstream->GetBsOffset() + curr_slice->fakeBitstream->m_nOutstandingBits - ob;
Ipp32s d = SSD16x16(cur_mb.mbPtr, cur_mb.mbPitchPixels, m_pReconstructFrame->m_pYPlane + m_pMBOffsets[uMB].uLumaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field], cur_mb.mbPitchPixels);
Ipp32s uOffset = m_pMBOffsets[uMB].uChromaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field];
if (m_PicParamSet.chroma_format_idc != 0) {
//TODO 420 only !!
d += SSD8x8(m_pCurrentFrame->m_pUPlane + uOffset, cur_mb.mbPitchPixels, m_pReconstructFrame->m_pUPlane + uOffset, cur_mb.mbPitchPixels);
d += SSD8x8(m_pCurrentFrame->m_pVPlane + uOffset, cur_mb.mbPitchPixels, m_pReconstructFrame->m_pVPlane + uOffset, cur_mb.mbPitchPixels);
}
*puAIMBSAD = d + cur_mb.lambda * bs;
curr_slice->m_pbitstream = pBitstream;
*cur_mb.LocalMacroblockInfo = sLocalMBinfo;
*cur_mb.GlobalMacroblockInfo = sGlobalMBinfo;
} else {
Ipp32s iQP = getLumaQP51(curr_slice->m_cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.bit_depth_luma);
*puAIMBSAD += BITS_COST(24, glob_RDQM[iQP]);
}
} // AdvancedIntraModeSelectOneMacroblock
static const Ipp8u uBlockURPredOK[] = {
// luma
0xff, 0xff, 0xff, 0,
0xff, 0xff, 0xff, 0,
0xff, 0xff, 0xff, 0,
0xff, 0, 0xff, 0
};
////////////////////////////////////////////////////////////////////////////////
//
// GetBlockPredPels
//
// Obtains the above and left prediction pels for the 4x4 block,
// following edge rules.
//
// The prediction pel buffer is ordered as follows:
//
// [0]: M
// [1..8]: A..H
// [9..12] I..L
//
// Predictors M and E..H are used only for the diagonal modes
// (modes 3 and greater).
//
////////////////////////////////////////////////////////////////////////////////
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::GetBlockPredPels(
H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice,
PixType* pLeftRefBlock, // pointer to block in reference picture
Ipp32u uLeftPitch, // of source data
PixType* pAboveRefBlock, // pointer to block in reference picture
Ipp32u uAbovePitch, // of source data
PixType* pAboveLeftRefBlock, // pointer to block in reference picture
Ipp32u uAboveLeftPitch, // of source data
Ipp32u uBlock, // 0..15 for luma blocks only
PixType* PredPel) // result here
{
Ipp32s raster_block = block_subblock_mapping[uBlock];
bool bLeft = false;
if (BLOCK_IS_ON_LEFT_EDGE(raster_block)){
bLeft = curr_slice->m_cur_mb.CurrentBlockNeighbours.mbs_left[raster_block / 4].mb_num < 0;
}
bool bTop = false;
if (BLOCK_IS_ON_TOP_EDGE(raster_block)){
bTop = curr_slice->m_cur_mb.CurrentBlockNeighbours.mb_above.mb_num < 0;
}
// get predictor pels from above and left blocks, following edge rules
if (bTop && bLeft) {
P_A = P_B = P_C = P_D =
P_I = P_J = P_K = P_L = 1<<(m_PicParamSet.bit_depth_luma - 1);
}else if (bTop && !bLeft) {
for (Ipp32s i = 0; i < 4; i++) {
PredPel[i+1] = PredPel[i+9] = (pLeftRefBlock + i*uLeftPitch)[-1];
}
}else if (!bTop && bLeft) {
for (Ipp32s i = 0; i < 4; i++) {
PredPel[i+1] = PredPel[i+9] =(pAboveRefBlock - uAbovePitch)[i];
}
}else {
for (Ipp32s i = 0; i < 4; i++) {
PredPel[i+1] = (pAboveRefBlock - uAbovePitch)[i];
PredPel[i+9] = (pLeftRefBlock + i*uLeftPitch)[-1];
}
// for diagonal modes
P_Z = (pAboveLeftRefBlock - uAboveLeftPitch)[-1];
}
if (!bTop) {
// Get EFGH, predictors pels above and to the right of the block.
// Use D when EFGH are not valid, which is when the block is on
// the right edge of the MB and the MB is at the right edge of
// the picture; or when the block is on the right edge of the MB
// but not in the top row.
bool bRight = raster_block == 3 ?
curr_slice->m_cur_mb.CurrentBlockNeighbours.mb_above_right.mb_num < 0 : false;
if (uBlockURPredOK[uBlock] == 0 || bRight)
{
P_E = P_F = P_G = P_H = P_D;
} else {
P_E = (pAboveRefBlock - uAbovePitch)[4];
P_F = (pAboveRefBlock - uAbovePitch)[5];
P_G = (pAboveRefBlock - uAbovePitch)[6];
P_H = (pAboveRefBlock - uAbovePitch)[7];
}
}
} // GetBlockPredPels
////////////////////////////////////////////////////////////////////////////////
//
// GetPredBlock
//
// Find advanced intra prediction block, store in PredBuf, which has a pitch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -