📄 umc_h264_core_enc.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 <stddef.h>
#include <math.h>
#include "ippdefs.h"
#include "umc_h264_video_encoder.h"
#include "umc_h264_core_enc.h"
#include "umc_h264_tables.h"
#include "umc_h264_to_ipp.h"
#include "umc_h264_bme.h"
#include "umc_h264_deblocking_tools.h"
// Table to obtain edge info for a 4x4 block of a MB. The table entry when
// OR'd with the edge info for the MB, results in edge info for the block.
//
// H264 4x4 Block ordering in a 16x16 Macroblock and edge assignments
//
// ULC = Upper Left Corner, U = Upper Edge
// L = Left Edge, R = Right Edge
//
// luma (Y) chroma (U) chroma (V)
//
// +-U--+-U--+-U--+-U--+ +-U--+-U--+ +-U--+-U--+
// | | | | | | | | | | |
// ULC--> L 0 | 1 | 4 | 5 R ULC--> L 16 | 17 R ULC--> L 20 | 21 R
// | | | | | | | | | | |
// +----+----+----+----+ +----+----+ +----+----+
// | | | | | | | | | | |
// L 2 | 3 | 6 | 7 R L 18 | 19 R L 22 | 23 R
// | | | | | | | | | | |
// +----+----+----+----+ +----+----+ +----+----+
// | | | | |
// L 8 | 9 | 12 | 13 R
// | | | | |
// +----+----+----+----+
// | | | | |
// L 10 | 11 | 14 | 15 R
// | | | | |
// +----+----+----+----+
//
// This table provides easy look-up by block number to determine
// which edges is does NOT border on.
namespace UMC_H264_ENCODER
{
// Number of bits (header plus residual) that triggers a MB to be recoded with a higher QP (up to twice) or in PCM mode.
#define MB_RECODE_THRESH 2750
// Slices with Intra MBs over this percentage may be recoded as Intra
#define INTRA_PERCENTAGE_THRESHOLD 0.75
#if ((defined(__GNUC__) && defined(__APPLE__) && !defined(__ICC)))
template<class PixType, class CoeffsType>
Ipp8s H264CoreEncoder<PixType,CoeffsType>::GetReferenceField(Ipp8s *pFields,Ipp8s RefIndex)
{
if (RefIndex<0) return -1;
else{
VM_ASSERT(pFields[RefIndex]>=0);
return pFields[RefIndex];
}
}
template<class PixType, class CoeffsType>
EncoderRefPicListStruct<PixType>* H264CoreEncoder<PixType, CoeffsType>::GetRefPicList(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice, Ipp32u List,Ipp32s mb_cod_type,Ipp32s is_bottom_mb)
{
EncoderRefPicListStruct<PixType> *pList;
if (List == LIST_0)
pList = &curr_slice->m_TempRefPicList[mb_cod_type][is_bottom_mb].m_RefPicListL0;
else
pList = &curr_slice->m_TempRefPicList[mb_cod_type][is_bottom_mb].m_RefPicListL1;
return pList;
} // RefPicLists
#endif
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::Intra16x16SelectAndPredict(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice, Ipp32u uMB, Ipp32u *puAIMBSAD, PixType *pPredBuf)
{
T_AIMode BestMode;
H264CurrentMacroblockDescriptor<PixType, CoeffsType>& cur_mb = curr_slice->m_cur_mb;
if( m_Analyse & ANALYSE_RD_OPT ){
*puAIMBSAD = Intra16x16SelectRD(curr_slice, cur_mb.mbPtr, m_pReconstructFrame->m_pYPlane + m_pMBOffsets[uMB].uLumaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field], cur_mb.mbPitchPixels, &BestMode, pPredBuf);
}else{
*puAIMBSAD = AIModeSelectOneMB_16x16(curr_slice, cur_mb.mbPtr, m_pReconstructFrame->m_pYPlane + m_pMBOffsets[uMB].uLumaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field], cur_mb.mbPitchPixels, &BestMode, pPredBuf);
}
curr_slice->m_cur_mb.LocalMacroblockInfo->intra_16x16_mode = BestMode; // Selected mode is stored in block 0
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_16x16;
CEncAndRec16x16IntraMB(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;
}
} // Intra16x16SelectAndPredict
template <class PixType, class CoeffsType>
Ipp32u H264CoreEncoder<PixType,CoeffsType>::MB_Decision(H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice, Ipp32s uMB)
{
Ipp32u best_sad, uAIMBSAD_16x16, uAIMBSAD_4x4, uAIMBSAD_8x8, uBestIntraSAD;
MB_Type uBestIntraMBType;
bool bIntra8x8 = false;
T_AIMode intra_types_save[16];
H264CurrentMacroblockDescriptor<PixType, CoeffsType> &cur_mb = curr_slice->m_cur_mb;
Ipp8u uMBQP = getLumaQP51(cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.bit_depth_luma);
Ipp32s MBHasEdges;
best_sad = uAIMBSAD_4x4 = uAIMBSAD_8x8 = uBestIntraSAD = MAX_SAD>>1;
cur_mb.LocalMacroblockInfo->cbp_bits =
cur_mb.LocalMacroblockInfo->cbp_bits_chroma =
cur_mb.LocalMacroblockInfo->cbp =
cur_mb.LocalMacroblockInfo->intra_chroma_mode = 0;
cur_mb.LocalMacroblockInfo->sbdir[0] =
cur_mb.LocalMacroblockInfo->sbdir[1] =
cur_mb.LocalMacroblockInfo->sbdir[2] =
cur_mb.LocalMacroblockInfo->sbdir[3] = D_DIR_FWD;
cur_mb.LocalMacroblockInfo->cbp_luma = 0xffff;
cur_mb.LocalMacroblockInfo->cbp_chroma = 0xffffffff;
cur_mb.LocalMacroblockInfo->best_distortion = MAX_SAD;
curr_slice->m_uIntraCBP4x4 = 0xffff;
curr_slice->m_uIntraCBP8x8 = 0xffff;
curr_slice->m_uMBInterSAD = MAX_SAD;
if (curr_slice->m_slice_type != INTRASLICE) {
#ifdef H264_NEW_ME
curr_slice->m_uMBInterSAD = (BPREDSLICE == curr_slice->m_slice_type) ? ME_B(curr_slice) : ME_P(curr_slice);
#else
CMEOneMB(curr_slice, uMB, &curr_slice->m_uMBInterSAD);
#endif
// MB type classification. Only need to change anything if INTRA is chosen, as the ME function filled in MB info for best INTER mode and cbp's.
// save INTER results for possible later switch back to INTER
MBTypeValue MBTypeInter = cur_mb.GlobalMacroblockInfo->mbtype;
curr_slice->m_uInterCBP4x4 = cur_mb.LocalMacroblockInfo->cbp_luma;
curr_slice->m_InterMBType = static_cast<MB_Type>(cur_mb.GlobalMacroblockInfo->mbtype);
curr_slice->m_InterMB8x8PackFlag = pGetMB8x8TSPackFlag(cur_mb.GlobalMacroblockInfo);
cur_mb.mb[MBTYPE_INTER].sad = curr_slice->m_uMBInterSAD;
Ipp32s mb_type = cur_mb.GlobalMacroblockInfo->mbtype;
if (((m_Analyse & ANALYSE_RD_OPT) || (m_Analyse & ANALYSE_RD_MODE)) || (!((mb_type == MBTYPE_DIRECT) || (mb_type == MBTYPE_SKIPPED) || (curr_slice->m_uMBInterSAD < EmptyThreshold[uMBQP])))) {
Intra16x16SelectAndPredict(curr_slice, uMB, &uAIMBSAD_16x16, cur_mb.mb16x16.prediction);
cur_mb.mb[MBTYPE_INTRA_16x16].sad = uBestIntraSAD = uAIMBSAD_16x16;
uBestIntraMBType = MBTYPE_INTRA_16x16;
// FAST intra decision
if (uAIMBSAD_16x16 <= 2 * curr_slice->m_uMBInterSAD && ((m_Analyse & ANALYSE_RD_OPT) || (m_Analyse & ANALYSE_RD_MODE) || (curr_slice->m_uMBInterSAD >= rd_quant_intra_min[uMBQP]))) {
if ((m_Analyse & ANALYSE_I_4x4) || (m_info.transform_8x8_mode_flag && (m_Analyse & ANALYSE_I_8x8))) {
#ifndef H264_RD_OPT
// Use edge detection to determine if the MB is a flat region
ippiEdgesDetect16x16(cur_mb.mbPtr, cur_mb.mbPitchPixels, EdgePelDiffTable[uMBQP], EdgePelCountTable[uMBQP], &MBHasEdges);
if (MBHasEdges) {
#endif
if (m_info.transform_8x8_mode_flag && (m_Analyse & ANALYSE_I_8x8)) {
pSetMB8x8TSFlag(curr_slice->m_cur_mb.GlobalMacroblockInfo, true);
AdvancedIntraModeSelectOneMacroblock8x8(curr_slice, uMB, uBestIntraSAD, &uAIMBSAD_8x8);
//Save intra_types
memcpy(intra_types_save, curr_slice->m_cur_mb.intra_types, 16*sizeof(T_AIMode));
if (uAIMBSAD_8x8 < uBestIntraSAD) {
uBestIntraSAD = uAIMBSAD_8x8;
uBestIntraMBType = MBTYPE_INTRA;
bIntra8x8 = true;
}
pSetMB8x8TSFlag(curr_slice->m_cur_mb.GlobalMacroblockInfo, false);
}
if (m_Analyse & ANALYSE_I_4x4) {
AdvancedIntraModeSelectOneMacroblock(curr_slice, uMB, uBestIntraSAD, &uAIMBSAD_4x4);
cur_mb.mb[MBTYPE_INTRA].sad = uAIMBSAD_4x4;
#ifdef H264_RD_OPT
memcpy(curr_slice->m_cur_mb.mb[MBTYPE_INTRA].intra_types, curr_slice->m_cur_mb.intra_types, 16*sizeof(T_AIMode));
#endif
if (uAIMBSAD_4x4 < uBestIntraSAD) {
uBestIntraSAD = uAIMBSAD_4x4;
uBestIntraMBType = MBTYPE_INTRA;
bIntra8x8 = false;
}
}
#ifndef H264_RD_OPT
}
#endif
}
}
curr_slice->m_uMBIntraSAD = uBestIntraSAD;
if (!((m_Analyse & ANALYSE_RD_OPT) || (m_Analyse & ANALYSE_RD_MODE)) && (m_Analyse & ANALYSE_ME_CHROMA) && m_PicParamSet.chroma_format_idc != 0) {
Ipp8u mode;
Ipp32s uOffset = m_pMBOffsets[uMB].uChromaOffset[m_is_cur_pic_afrm][curr_slice->m_is_cur_mb_field];
PixType* pPredBuf = cur_mb.mbChromaIntra.prediction;
//Get intra chroma prediction
uBestIntraSAD += AIModeSelectChromaMBs_8x8(curr_slice, m_pCurrentFrame->m_pUPlane + uOffset, m_pReconstructFrame->m_pUPlane + uOffset,
m_pCurrentFrame->m_pVPlane + uOffset, m_pReconstructFrame->m_pVPlane + uOffset, cur_mb.mbPitchPixels, &mode, pPredBuf, pPredBuf+8);
}
if (!((m_Analyse & ANALYSE_RD_OPT) || (m_Analyse & ANALYSE_RD_MODE)) && (curr_slice->m_slice_type == BPREDSLICE))
uBestIntraSAD += BITS_COST(9, glob_RDQM[uMBQP]);
if (uBestIntraSAD < curr_slice->m_uMBInterSAD) {
cur_mb.GlobalMacroblockInfo->mbtype = static_cast<MBTypeValue>(uBestIntraMBType);
pSetMB8x8TSPackFlag(curr_slice->m_cur_mb.GlobalMacroblockInfo, bIntra8x8);
if (uBestIntraMBType == MBTYPE_INTRA && !bIntra8x8)
cur_mb.LocalMacroblockInfo->cbp_luma = curr_slice->m_uIntraCBP4x4;
else if (uBestIntraMBType == MBTYPE_INTRA && bIntra8x8) {
cur_mb.LocalMacroblockInfo->cbp_luma = curr_slice->m_uIntraCBP8x8;
//Restore intra_types
memcpy( curr_slice->m_cur_mb.intra_types, intra_types_save, 16*sizeof(T_AIMode));
} else
cur_mb.LocalMacroblockInfo->cbp_luma = 0xffff;
cur_mb.LocalMacroblockInfo->cbp_chroma = 0xffffffff;
curr_slice->m_Intra_MB_Counter++;
best_sad = uBestIntraSAD;
} else {
cur_mb.GlobalMacroblockInfo->mbtype = MBTypeInter;
cur_mb.LocalMacroblockInfo->cbp_luma = curr_slice->m_uInterCBP4x4;
best_sad = curr_slice->m_uMBInterSAD;
pSetMB8x8TSPackFlag(cur_mb.GlobalMacroblockInfo, curr_slice->m_InterMB8x8PackFlag);
}
} else {
best_sad = curr_slice->m_uMBInterSAD;
}
} else { // intra slice
Intra16x16SelectAndPredict(curr_slice, uMB, &uAIMBSAD_16x16, cur_mb.mb16x16.prediction);
uBestIntraMBType = MBTYPE_INTRA_16x16;
cur_mb.mb[MBTYPE_INTRA_16x16].sad = best_sad = uAIMBSAD_16x16;
if ((m_Analyse & ANALYSE_I_4x4) || (m_info.transform_8x8_mode_flag && (m_Analyse & ANALYSE_I_8x8))) {
#ifndef H264_RD_OPT
// Use edge detection to determine if the MB is a flat region
ippiEdgesDetect16x16(cur_mb.mbPtr, cur_mb.mbPitchPixels, EdgePelDiffTable[uMBQP], EdgePelCountTable[uMBQP], &MBHasEdges);
if (MBHasEdges) {
#else
// cur_mb.mb[MBTYPE_INTRA_16x16].ssd = SSD16x16(cur_mb.mbPtr, cur_mb.mbPitchPixels, cur_mb.mb16x16.reconstruct, 16 );
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -