📄 mv-search.c
字号:
/*!
*************************************************************************************
* \file mv-search.c
*
* \brief
* Motion Vector Search, unified for B and P Pictures
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Stephan Wenger <stewe@cs.tu-berlin.de>
* - Inge Lille-Langoy <inge.lille-langoy@telenor.com>
* - Rickard Sjoberg <rickard.sjoberg@era.ericsson.se>
* - Stephan Wenger <stewe@cs.tu-berlin.de>
* - Jani Lainema <jani.lainema@nokia.com>
* - Detlev Marpe <marpe@hhi.de>
* - Thomas Wedi <wedi@tnt.uni-hannover.de>
* - Heiko Schwarz <hschwarz@hhi.de>
* - Alexis Michael Tourapis <alexismt@ieee.org>
*
*************************************************************************************
*/
#include "contributors.h"
#include <math.h>
#include <limits.h>
#include <time.h>
#include <sys/timeb.h>
#include "global.h"
#include "image.h"
#include "mv-search.h"
#include "refbuf.h"
#include "memalloc.h"
#include "mb_access.h"
#include "macroblock.h"
#include "mc_prediction.h"
#include "conformance.h"
// Motion estimation distortion header file
#include "me_distortion.h"
// Motion estimation search algorithms
#include "me_epzs.h"
#include "me_fullfast.h"
#include "me_fullsearch.h"
#include "me_umhex.h"
#include "me_umhexsmp.h"
#include "rdoq.h"
// Statistics, temporary
int max_mvd;
short* spiral_search_x;
short* spiral_search_y;
short* spiral_hpel_search_x;
short* spiral_hpel_search_y;
int* mvbits;
int* refbits;
int* byte_abs;
int**** motion_cost;
int byte_abs_range;
static int diff [16];
static int diff64[64];
static imgpel orig_pic [768];
int (*IntPelME) (Macroblock *, imgpel *, short, int, int, char ***, short ****,
int, int, int, short[2], short[2], int, int, int, int);
int (*BiPredME) (Macroblock *, imgpel *, short, int, int, char ***, short ****,
int, int, int, short[2], short[2], short[2], short[2], int, int, int, int, int);
int (*SubPelBiPredME) (imgpel* orig_pic, short ref, int list, int pic_pix_x, int pic_pix_y,
int blocktype, short pred_mv1[2], short pred_mv2[2], short mv1[2], short mv2[2],
int search_pos2, int search_pos4, int min_mcost, int* lambda_factor, int apply_weights);
int (*SubPelME) (imgpel* orig_pic, short ref, int list, int list_offset, int pic_pix_x, int pic_pix_y,
int blocktype, short pred_mv[2], short mv[2],
int search_pos2, int search_pos4, int min_mcost, int* lambda_factor, int apply_weights);
int BlockMotionSearch (Macroblock *currMB, short,int,int,int,int,int, int*);
int BiPredBlockMotionSearch(Macroblock *currMB, short[2], short*, short, int, int, int, int , int, int, int*);
int GetSkipCostMB (Macroblock *currMB);
extern ColocatedParams *Co_located;
extern const short block_type_shift_factor[8];
/*!
************************************************************************
* \brief
* Initialize ME engine
************************************************************************
*/
void init_ME_engine(int SearchMode)
{
switch (SearchMode)
{
case EPZS:
IntPelME = EPZSPelBlockMotionSearch;
BiPredME = EPZSBiPredBlockMotionSearch;
SubPelBiPredME = (params->EPZSSubPelMEBiPred) ? EPZSSubPelBlockSearchBiPred : SubPelBlockSearchBiPred;
SubPelME = (params->EPZSSubPelME) ? EPZSSubPelBlockMotionSearch : SubPelBlockMotionSearch;
break;
case UM_HEX:
IntPelME = UMHEXIntegerPelBlockMotionSearch;
BiPredME = UMHEXBipredIntegerPelBlockMotionSearch;
SubPelBiPredME = SubPelBlockSearchBiPred;
SubPelME = UMHEXSubPelBlockME;
break;
case UM_HEX_SIMPLE:
IntPelME = smpUMHEXIntegerPelBlockMotionSearch;
BiPredME = smpUMHEXBipredIntegerPelBlockMotionSearch;
SubPelBiPredME = SubPelBlockSearchBiPred;
SubPelME = smpUMHEXSubPelBlockME;
break;
case FULL_SEARCH:
IntPelME = FullPelBlockMotionSearch;
BiPredME = FullPelBlockMotionBiPred;
SubPelBiPredME = SubPelBlockSearchBiPred;
SubPelME = SubPelBlockMotionSearch;
break;
case FAST_FULL_SEARCH:
default:
IntPelME = FastFullPelBlockMotionSearch;
BiPredME = FullPelBlockMotionBiPred;
SubPelBiPredME = SubPelBlockSearchBiPred;
SubPelME = SubPelBlockMotionSearch;
break;
}
}
/*!
************************************************************************
* \brief
* Prepare Motion Estimation parameters for single list ME
************************************************************************
*/
void PrepareMEParams(int apply_weights, int ChromaMEEnable, int list, int ref)
{
if (apply_weights)
{
weight_luma = wp_weight[list][ref][0];
offset_luma = wp_offset[list][ref][0];
if ( ChromaMEEnable)
{
weight_cr[0] = wp_weight[list][ref][1];
weight_cr[1] = wp_weight[list][ref][2];
offset_cr[0] = wp_offset[list][ref][1];
offset_cr[1] = wp_offset[list][ref][2];
}
}
}
/*!
************************************************************************
* \brief
* Prepare Motion Estimation parameters for bipred list ME
************************************************************************
*/
void PrepareBiPredMEParams(int apply_weights, int ChromaMEEnable, int list, int list_offset, int ref)
{
if (apply_weights)
{
if (list == LIST_0)
{
weight1 = wbp_weight[list_offset ][ref][0][0];
weight2 = wbp_weight[list_offset + LIST_1][ref][0][0];
offsetBi = (wp_offset[list_offset ][ref][0] + wp_offset[list_offset + LIST_1][ref][0] + 1)>>1;
if ( ChromaMEEnable)
{
weight1_cr[0] = wbp_weight[list_offset ][ref][0][1];
weight1_cr[1] = wbp_weight[list_offset ][ref][0][2];
weight2_cr[0] = wbp_weight[list_offset + LIST_1][ref][0][1];
weight2_cr[1] = wbp_weight[list_offset + LIST_1][ref][0][2];
offsetBi_cr[0] = (wp_offset[list_offset ][ref][1] + wp_offset[list_offset + LIST_1][ref][1] + 1) >> 1;
offsetBi_cr[1] = (wp_offset[list_offset ][ref][2] + wp_offset[list_offset + LIST_1][ref][2] + 1) >> 1;
}
}
else
{
weight1 = wbp_weight[list_offset + LIST_1][0 ][ref][0];
weight2 = wbp_weight[list_offset ][0 ][ref][0];
offsetBi = (wp_offset[list_offset + LIST_1][0][0] + wp_offset[list_offset][0][0] + 1)>>1;
if ( ChromaMEEnable)
{
weight1_cr[0] = wbp_weight[list_offset + LIST_1][0 ][ref][1];
weight1_cr[1] = wbp_weight[list_offset + LIST_1][0 ][ref][2];
weight2_cr[0] = wbp_weight[list_offset ][0 ][ref][1];
weight2_cr[1] = wbp_weight[list_offset ][0 ][ref][2];
offsetBi_cr[0] = (wp_offset[list_offset + LIST_1][0 ][1] + wp_offset[list_offset ][0 ][1] + 1) >> 1;
offsetBi_cr[1] = (wp_offset[list_offset + LIST_1][0 ][2] + wp_offset[list_offset ][0 ][2] + 1) >> 1;
}
}
}
else
{
weight1 = 1<<luma_log_weight_denom;
weight2 = 1<<luma_log_weight_denom;
offsetBi = 0;
if ( ChromaMEEnable)
{
weight1_cr[0] = 1<<chroma_log_weight_denom;
weight1_cr[1] = 1<<chroma_log_weight_denom;
weight2_cr[0] = 1<<chroma_log_weight_denom;
weight2_cr[1] = 1<<chroma_log_weight_denom;
offsetBi_cr[0] = 0;
offsetBi_cr[1] = 0;
}
}
}
/*!
************************************************************************
* \brief
* Set motion vector predictor
************************************************************************
*/
void SetMotionVectorPredictor (Macroblock *currMB,
short pmv[2],
char **refPic,
short ***tmp_mv,
short ref_frame,
int list,
int mb_x,
int mb_y,
int blockshape_x,
int blockshape_y)
{
int mv_a, mv_b, mv_c, pred_vec=0;
int mvPredType, rFrameL, rFrameU, rFrameUR;
int hv;
PixelPos block_a, block_b, block_c, block_d;
int *mb_size = img->mb_size[IS_LUMA];
get4x4Neighbour(currMB, mb_x - 1, mb_y , mb_size, &block_a);
get4x4Neighbour(currMB, mb_x, mb_y - 1, mb_size, &block_b);
get4x4Neighbour(currMB, mb_x + blockshape_x, mb_y - 1, mb_size, &block_c);
get4x4Neighbour(currMB, mb_x - 1, mb_y - 1, mb_size, &block_d);
if (mb_y > 0)
{
if (mb_x < 8) // first column of 8x8 blocks
{
if (mb_y == 8 )
{
if (blockshape_x == 16) block_c.available = 0;
}
else if (mb_x+blockshape_x == 8)
{
block_c.available = 0;
}
}
else if (mb_x+blockshape_x == 16)
{
block_c.available = 0;
}
}
if (!block_c.available)
{
block_c = block_d;
}
mvPredType = MVPRED_MEDIAN;
if (!img->MbaffFrameFlag)
{
rFrameL = block_a.available ? refPic[block_a.pos_y][block_a.pos_x] : -1;
rFrameU = block_b.available ? refPic[block_b.pos_y][block_b.pos_x] : -1;
rFrameUR = block_c.available ? refPic[block_c.pos_y][block_c.pos_x] : -1;
}
else
{
if (currMB->mb_field)
{
rFrameL = block_a.available
? (img->mb_data[block_a.mb_addr].mb_field
? refPic[block_a.pos_y][block_a.pos_x]
: refPic[block_a.pos_y][block_a.pos_x] * 2) : -1;
rFrameU = block_b.available
? (img->mb_data[block_b.mb_addr].mb_field
? refPic[block_b.pos_y][block_b.pos_x]
: refPic[block_b.pos_y][block_b.pos_x] * 2) : -1;
rFrameUR = block_c.available
? (img->mb_data[block_c.mb_addr].mb_field
? refPic[block_c.pos_y][block_c.pos_x]
: refPic[block_c.pos_y][block_c.pos_x] * 2) : -1;
}
else
{
rFrameL = block_a.available
? (img->mb_data[block_a.mb_addr].mb_field
? refPic[block_a.pos_y][block_a.pos_x] >>1
: refPic[block_a.pos_y][block_a.pos_x]) : -1;
rFrameU = block_b.available
? (img->mb_data[block_b.mb_addr].mb_field
? refPic[block_b.pos_y][block_b.pos_x] >>1
: refPic[block_b.pos_y][block_b.pos_x]) : -1;
rFrameUR = block_c.available
? (img->mb_data[block_c.mb_addr].mb_field
? refPic[block_c.pos_y][block_c.pos_x] >>1
: refPic[block_c.pos_y][block_c.pos_x]) : -1;
}
}
/* Prediction if only one of the neighbors uses the reference frame
* we are checking
*/
if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)
mvPredType = MVPRED_L;
else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)
mvPredType = MVPRED_U;
else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)
mvPredType = MVPRED_UR;
// Directional predictions
if(blockshape_x == 8 && blockshape_y == 16)
{
if(mb_x == 0)
{
if(rFrameL == ref_frame)
mvPredType = MVPRED_L;
}
else
{
if( rFrameUR == ref_frame)
mvPredType = MVPRED_UR;
}
}
else if(blockshape_x == 16 && blockshape_y == 8)
{
if(mb_y == 0)
{
if(rFrameU == ref_frame)
mvPredType = MVPRED_U;
}
else
{
if(rFrameL == ref_frame)
mvPredType = MVPRED_L;
}
}
for (hv=0; hv < 2; hv++)
{
if (!img->MbaffFrameFlag || hv==0)
{
mv_a = block_a.available ? tmp_mv[block_a.pos_y][block_a.pos_x][hv] : 0;
mv_b = block_b.available ? tmp_mv[block_b.pos_y][block_b.pos_x][hv] : 0;
mv_c = block_c.available ? tmp_mv[block_c.pos_y][block_c.pos_x][hv] : 0;
}
else
{
if (currMB->mb_field)
{
mv_a = block_a.available ? img->mb_data[block_a.mb_addr].mb_field
? tmp_mv[block_a.pos_y][block_a.pos_x][hv]
: tmp_mv[block_a.pos_y][block_a.pos_x][hv] / 2
: 0;
mv_b = block_b.available ? img->mb_data[block_b.mb_addr].mb_field
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -