📄 umc_h264_me.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 <string.h>#include <limits.h>#include "umc_h264_tables.h" // for const Ipp8u rd_quant[];#include "umc_h264_bme.h"#include "umc_h264_video_encoder.h"//#define TRACE_MV_PRED//#define PREV_PRED // Uncommenting this substitutes a MV from a previously // encoded reference frame for the LeftMV in RD Calculations // that use predicted MV values//#define UL_PRED // Uncommenting this substitutes a MV from the (when avail) UL MB // for the LeftMV in RD Calculations that use predicted MV values//#define NULL_PRED // Uncommenting this substitutes a Null MV (0,0) // for the LeftMV in RD Calculations that use predicted MV values#if (defined(PREV_PRED) || defined(UL_PRED) || defined(NULL_PRED))#define NO_LEFT_DEP#endif // PREV_PRED || UL_PRED || NULL_PRED//#define NO_EMPTY_THRESH#define B_EARLY_EXIT//#define P_EARLY_EXIT#define BESTOF5_EARLY_EXIT // skip rest of search if current best is good enough//#define FORCE_INTER//#define NO_SUBPEL_SEARCH//#define PRINT_MVS//#define BFRAME_FORCE_FUTURE_REFERENCE // for B frames//#define BFRAME_FORCE_PREVIOUS_REFERENCE // for B frames//#define BFRAME_NO_DIRECT_MODE // for B frames//#define BFRAME_NO_BIPRED_MODE // for B frames//#define BFRAME_NO_BIPRED_MODE_SUBDIV//#define BFRAME_PRINT_MVS//#define FULL_SUBPEL_SEARCH // Otherwise, conjugate...// Macro definitions used to make things a little easier to read...#define SAD16 SAD16x16Block#define SAD8 SAD8x8Block#define SAD4 SAD4x4Block#define SAD16SB4 SAD16x16Block_Sb4#define SAD16SB16 SAD16x16Block_Sb16// SAD functions using fixed pitch for second source#define SAD16_P16 SAD16x16Block_P16#define SAD8_P16 SAD8x8Block_P16#define SAD4_P16 SAD4x4Block_P16// Subpel interpolation function//#define SP_INTERP(x,y) ((*m_pCurrentFrame->InterpFunc)[(y)][(x)])#define RANGECHECK(x, low, high) (((x) >= (low)) && ((x) <= (high)))#define MAXINTVEC (31) // ((max Ipp8s) - (subpel search range)) / subpel factor // (127 - 3) / 4// Macro to verify that vectors will not exceed the size of an Ipp8s after// conversion from integer to subpel. Theoretically this is possible even though// the signature search only searches +/- 32 around 0 (thus a max vector of// +/- 96 plus the subpel search of =/- 2), because the initial integer search// positions include predictor vectors, which could already be at a +/- 32 point.// Then the integer search goes a little further, the new larger vector is a// future predictor, so the future search go could even a little further, ...// The code currently converts the vectors to Ipp8s from Ipp32s without clipping on// the assumption that the above scenario in practice will not occur. The// macros are used in HiveAsserts to verify this assumption. Clipping may need// to be added if the assumption proves false.// 01/28/00 update: The asserts have been hit a few times, indicating vectors// are sometimes exceeding Ipp8s size, so clipping has been added when calculating// the search ranges (left, right, up, down).#define VINTRANGE(v) RANGECHECK((v), -MAXINTVEC-1, MAXINTVEC)// LUT for MV bit usage.// FIXME: This table is way bigger than need be. It should be no larger than 256 entries.// FIXE RJR: 256 is too small because the index into the table is the sum of two// vectors (predictor, current position). The range of predictor is theoretically// -128 to +127 and current position range is currently -32*3 to +32*3. I'm// temporarily restoring the table to it's original larger size, which is too// big, but actually should do no harm.//#define BITSFORMV_OFFSET 128 // (1+2+4+8+16+11*32)#define BITSFORMV_OFFSET (1+2+4+8+16+11*32)#define MVBITS(v) (BitsForMV[(v)+BITSFORMV_OFFSET])using namespace UMC_H264_ENCODER;namespace UMC{const Ipp8s BitsForMV [BITSFORMV_OFFSET + 1 + BITSFORMV_OFFSET] = { 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, // -256 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, // -128 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, // -64 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, // -32 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, // -16 9, 9, 9, 9, 9, 9, 9, 9, // -8 7, 7, 7, 7, // -4 5, 5, // -2 3, // -1 1, // 0 3, // 1 5, 5, // 2 7, 7, 7, 7, // 4 9, 9, 9, 9, 9, 9, 9, 9, // 8 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, // 16 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, // 32 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, // 64 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, // 128 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, // 256 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19};Ipp16s RDQM[52][39];bool bRDQMInitialized = false;enum BlockBestMode_8x8{ MODE_8x8, MODE_8x4, MODE_4x8, MODE_4x4,#ifndef BFRAME_NO_DIRECT_MODE MODE_DIRECT_8x8,#endif};////////////////////////////////////////////////////////////////////////////////// MVConstraint////////////////////////////////////////////////////////////////////////////////#if defined _DEBUGIpp32u MVConstraint(Ipp32s x, Ipp32s y, Ipp16s *pRDQM){ return (pRDQM[MVBITS(x) + MVBITS(y)]*1);}#else#define MVConstraint(x, y, pRDQM) (pRDQM[MVBITS(x) + MVBITS(y)])#endif // _DEBUGinline int RefConstraint(int ref_idx, int active_refs, Ipp16s *pRDQM){ if (active_refs == 1) return 0; if (active_refs > 2) { return pRDQM[MVBITS(ref_idx)]; }else{ return 0;//pRDQM[ref_idx ? 2 : 1]; }}#define MVADJUST(ptr, pitch, x, y) ((ptr) + Ipp32s((pitch)*(y) + (x)))////////////////////////////////////////////////////////////////////////////////// FindBestInitialMV// Return the best Initial 16x16 MV from the four possible candidates:// 1) Zero MV// 2) Predicted MV// 3) Above MV// 4) Left MV////////////////////////////////////////////////////////////////////////////////bool H264VideoEncoder::FindBestInitialMV( const Ipp8u* pCurrent, const Ipp8u* pPrev, const Ipp32u uMB, // MB number bool bBSlice, T_ECORE_MV& BestMV16x16, // resulting Best MV Ipp32s& uBestSAD16x16e, // resulting Best RD-Opt Distortion Ipp32s& uBestSAD16x16NoRD, // resulting Distortion T_ECORE_MV& PredictedMV, // return the 16x16 predicted vector const Ipp32s xMin, const Ipp32s xMax, const Ipp32s yMin, const Ipp32s yMax){ Ipp32u i; Ipp32s uSAD16x16e, uSAD16x16NoRD; Ipp32s uPitch = m_pCurrentFrame->uPitch; bool bDone = true; T_ECORE_MV NullMV = {0, 0}; T_ECORE_MV MVPred[7]; T_ECORE_BIGMV mvDelta[1]; T_ECORE_MV *pMVRef; bool bBackwardFlag = (m_pCurrentFrame->pMBData[uMB].uMBType == MBTYPE_BACKWARD); const Ipp32s uFwdRatio = m_SliceHeader.DistScaleFactorMV[0];//todo switch to ref_idx const Ipp32s TR_RND = (1 << (TR_SHIFT - 1)); Ipp32u uQP = m_pCurrentFrame->pMBData[uMB].uMBQP; Ipp16s* pRDQM = RDQM[uQP]; // zero vector MVPred[0] = NullMV; Ipp32u uMVnum = 1; // For now, assume Inter 16x16 MB Type // Note, if MB_Type is changed to anything else, // review that the values for xPred and yPred below are // appropriate... Estimate_One_MV_Predictor(uMB, 0, bBackwardFlag, NULL, 4, 4, &PredictedMV, mvDelta); // VSI - TODO -- Change the 3 lines below to reflect actual _frame_ edges. // Will improve Best of 5 for sliced images, by allowing Top/Left MVs to // contend across slice boundaries, which is OK, since there is no // dependency implied here. Particularly important since the Predictor // will not be as good in these cases. Ipp32u uMBEdgeType = m_pCurrentFrame->pMBData[uMB].uEdgeType; Ipp8u bMBIsNotOnTopEdge = uMBEdgeType & MBEdgeTypeIsNotTopEdge; Ipp8u bMBIsNotOnLeftEdge = uMBEdgeType & MBEdgeTypeIsNotLeftEdge; // vector for block 0 of the MB T_ECORE_MV *pMV, *pMVAbove;#ifndef NO_LEFT_DEP T_ECORE_MV *pMVLeft;#endif if (bBackwardFlag) { pMV = &m_pCurrentFrame->pMVL1[m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex]; } else { pMV = &m_pCurrentFrame->pMVL0[m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex]; } // predictors // note: at this point, uMVnum >= 1 MVPred[uMVnum].iMVx = (Ipp8s) (PredictedMV.iMVx / SubPelFactor); MVPred[uMVnum].iMVy = (Ipp8s) (PredictedMV.iMVy / SubPelFactor); for (i = 0; i < uMVnum; i ++) { if (MVPred[uMVnum].iMVx == MVPred[i].iMVx && MVPred[uMVnum].iMVy == MVPred[i].iMVy) break; if (i == uMVnum - 1 && MVPred[uMVnum].iMVx >= xMin && MVPred[uMVnum].iMVx <= xMax && MVPred[uMVnum].iMVy >= yMin && MVPred[uMVnum].iMVy <= yMax) { uMVnum ++; break; } } // above predictor if (bMBIsNotOnTopEdge) { pMVAbove = pMV - uWidthIn4x4Blocks; MVPred[uMVnum].iMVx = pMVAbove->iMVx / SubPelFactor; MVPred[uMVnum].iMVy = pMVAbove->iMVy / SubPelFactor; for (i = 0; i < uMVnum; i ++) { if (MVPred[uMVnum].iMVx == MVPred[i].iMVx && MVPred[uMVnum].iMVy == MVPred[i].iMVy) break; if (i == uMVnum - 1 && MVPred[uMVnum].iMVx >= xMin && MVPred[uMVnum].iMVx <= xMax && MVPred[uMVnum].iMVy >= yMin && MVPred[uMVnum].iMVy <= yMax) { uMVnum ++; break; } } } // This code properly selects and scales a MV from the reference frame(s) H264EncoderFrame *pPrevFrm = m_pCurrentFrame->GetRefPicList(0, LIST_0)->m_RefPicList[0]; // TO DO may be we should consider future MV if exist and B-slice //H264EncoderFrame *pFutFrm = m_pCurrentFrame->GetRefPicList(0, LIST_1)->m_RefPicList[0]; pMVRef = &pPrevFrm->pMVL0[m_pCurrentFrame->pMBOffsets[uMB].uFirstBlockIndex]; if (!bBSlice) { // Not B Slice, Magnitude is correct, simply copy vector MVPred[uMVnum].iMVx = pMVRef->iMVx; MVPred[uMVnum].iMVy = pMVRef->iMVy; } else { // B Slice // Forward vector, needs to be scaled, but direction is correct Ipp32s iSign; //iSign = pMVRef->iMVx < 0 ? -1 : 1; iSign = 1; MVPred[uMVnum].iMVx = (Ipp8s) ((uFwdRatio * pMVRef->iMVx + TR_RND * iSign) >> TR_SHIFT); iSign = pMVRef->iMVy < 0 ? -1 : 1; iSign = 1; MVPred[uMVnum].iMVy = (Ipp8s) ((uFwdRatio * pMVRef->iMVy + TR_RND * iSign) >> TR_SHIFT); if (bBackwardFlag) { // Backward vector, needs both scaling and direction changed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -