⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mv-search.c

📁 Mobile IP VCEG的信道模拟程序
💻 C
📖 第 1 页 / 共 4 页
字号:
// *************************************************************************************
// *************************************************************************************
// MV-Search.c	 Motion Vector Search, unufied for B and P Pictures
//
// Main contributors (see contributors.h for copyright, address and affiliation details)
//
// Stephan Wenger                  <stewe@cs.tu-berlin.de>			
// Inge Lille-Lang鴜               <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>
// *************************************************************************************
// *************************************************************************************

// To do list:

// 6. Unite the 1/2, 1/4 and1/8th pel search routines into a single routine
// 7. Clean up parameters, use sensemaking variable names
// 9. Implement fast leaky search, such as UBCs Diamond search


#include "contributors.h"

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include "global.h"
#include "mv-search.h"
#include "refbuf.h"


// Local function declarations

__inline int ByteAbs (int foo);

// These procedure pointers are used by motion_search() and one_eigthpel()
static pel_t (*PelY_18) (pel_t**, int, int);
static pel_t (*PelY_14) (pel_t**, int, int);
//static pel_t (*PelY_12) (pel_t**, int, int);
//static pel_t (*PelY_11)	(pel_t*, int, int);
static pel_t *(*PelYline_11) (pel_t *, int, int);

// The Spiral for spiral search
static int SpiralX[6561];
static int SpiralY[6561];

// The bit usage for MVs (currently lives in img-> mv_bituse and is used by
// b_frame.c, but should move one day to a more appropriate place
static int *MVBitUse;

// Statistics, temporary


// MV Cost returns the initial penalty for the motion vector representation.  Used
// by the various MV search routines for MV RD optimization

// ParameterResolution: the resolution of the vector parameter, 1, 2, 4, 8, eg 4 means 1/4 pel
// BitstreamResolution: the resolyution in which the bitstream is coded
//   ParameterResolution <= TargetResolution
//
// pred_x, pred_y: Predicted vector in BitstreamResolution
// Candidate_x, Candidate_y: Candidate vector in Parameter Resolution

static int MVCost (int ParameterResolution, int BitstreamResolution, 
		   int Blocktype, int qp,
		   int Pred_x, int Pred_y, 
		   int Candidate_x, int Candidate_y) {

	int Factor = BitstreamResolution/ParameterResolution;
	int Penalty;
	int len_x, len_y;

	len_x = Candidate_x * Factor - Pred_x; 
	len_y = Candidate_y * Factor - Pred_y;

	Penalty = (QP2QUANT[qp] * ( MVBitUse[absm (len_x)]+MVBitUse[absm(len_y)]) );

	if (img->type != B_IMG && Blocktype == 1 && Candidate_x == 0 && Candidate_y == 0)		// 16x16 and no motion
		Penalty -= QP2QUANT [qp] * 16;
	return Penalty;
}


#ifdef _RD_OPT_
/*****
 *****  motion vector cost for rate-distortion optimization
 *****
 */
static int MVCostLambda (int shift, double lambda,
			 int pred_x, int pred_y, int cand_x, int cand_y)
{
  return (int)(lambda * (MVBitUse[absm((cand_x << shift) - pred_x)] +
			 MVBitUse[absm((cand_y << shift) - pred_y)]   ));
}
#endif






/*****
 *****  setting the motion vector predictor
 *****
 */
void
SetMotionVectorPredictor (int pred[2], int **refFrArr, int ***tmp_mv,
			  int ref_frame, int mb_x, int mb_y, int blockshape_x, int blockshape_y)
{
	int block_x     = mb_x/BLOCK_SIZE;
	int block_y	= mb_y/BLOCK_SIZE;
	int pic_block_x = img->block_x + block_x;
	int pic_block_y = img->block_y + block_y;
	int mb_nr = img->current_mb_nr;
	int mb_width = img->width/16;
	int mb_available_up      = (img->mb_y == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-mb_width]);
	int mb_available_left    = (img->mb_x == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-1]);
	int mb_available_upleft  = (img->mb_x == 0 || img->mb_y == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-mb_width-1]);
	int mb_available_upright = (img->mb_x >= mb_width-1 || img->mb_y == 0) ? 0 : (img->slice_numbers[mb_nr] == img->slice_numbers[mb_nr-mb_width+1]);
	int block_available_up, block_available_left, block_available_upright, block_available_upleft;
	int mv_a, mv_b, mv_c, mv_d, pred_vec=0;
	int mvPredType, rFrameL, rFrameU, rFrameUR;
	int hv;

	/* D B C */
	/* A X   */

	/* 1 A, B, D are set to 0 if unavailable       */
	/* 2 If C is not available it is replaced by D */
	block_available_up   = mb_available_up   || (mb_y > 0);
	block_available_left = mb_available_left || (mb_x > 0);

	if (mb_y > 0)
		block_available_upright = mb_x+blockshape_x != MB_BLOCK_SIZE ? 1 : 0;
	else if (mb_x+blockshape_x != MB_BLOCK_SIZE)
		block_available_upright = block_available_up;
	else
		block_available_upright = mb_available_upright;

	if (mb_x > 0)
		block_available_upleft = mb_y > 0 ? 1 : block_available_up;
	else if (mb_y > 0)
		block_available_upleft = block_available_left;
	else
		block_available_upleft = mb_available_upleft;

	mvPredType = MVPRED_MEDIAN;

	rFrameL    = block_available_left    ? refFrArr[pic_block_y][pic_block_x-1]   : -1;
	rFrameU    = block_available_up      ? refFrArr[pic_block_y-1][pic_block_x]   : -1;
	rFrameUR   = block_available_upright ? refFrArr[pic_block_y-1][pic_block_x+blockshape_x/4] :
	             block_available_upleft  ? refFrArr[pic_block_y-1][pic_block_x-1] : -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 */

	else 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;
		}
	}
	else if(blockshape_x == 8 && blockshape_y == 4 && mb_x == 8)
		mvPredType = MVPRED_L;
	else if(blockshape_x == 4 && blockshape_y == 8 && mb_y == 8)
		mvPredType = MVPRED_U;

	for (hv=0; hv < 2; hv++)
	{
		mv_a = block_available_left    ? tmp_mv[hv][pic_block_y][pic_block_x-1+4]   : 0;
		mv_b = block_available_up      ? tmp_mv[hv][pic_block_y-1][pic_block_x+4]   : 0;
		mv_d = block_available_upleft  ? tmp_mv[hv][pic_block_y-1][pic_block_x-1+4] : 0;
		mv_c = block_available_upright ? tmp_mv[hv][pic_block_y-1][pic_block_x+blockshape_x/4+4] : mv_d;

		switch (mvPredType)
		{
		case MVPRED_MEDIAN:
			if(!(block_available_upleft || block_available_up || block_available_upright))
				pred_vec = mv_a;
			else
				pred_vec = mv_a+mv_b+mv_c-min(mv_a,min(mv_b,mv_c))-max(mv_a,max(mv_b,mv_c));
			break;

		case MVPRED_L:
			pred_vec = mv_a;
			break;
		case MVPRED_U:
			pred_vec = mv_b;
			break;
		case MVPRED_UR:
			pred_vec = mv_c;
			break;
		default:
			break;
		}

		pred[hv] = pred_vec;
	}
}






#ifdef _FAST_FULL_ME_
 
/*****
 *****  static variables for fast integer motion estimation
 *****
 */
static int	*search_setup_done;	// flag if all block SAD's have been calculated yet
static int	*search_center_x;	// absolute search center for fast full motion search
static int	*search_center_y;	// absolute search center for fast full motion search
static int  *pos_00;     		// position of (0,0) vector
static int	****BlockSAD;		// SAD for all blocksize, ref. frames and motion vectors



/*****
 *****  function creating arrays for fast integer motion estimation
 *****
 */
void
InitializeFastFullIntegerSearch (int search_range)
{
	int  i, j, k;
	int  max_pos = (2*search_range+1) * (2*search_range+1);

	if ((BlockSAD = (int****)malloc ((img->buf_cycle+1) * sizeof(int***))) == NULL)
		perror ("InitializeFastFullIntegerSearch");
	for (i = 0; i <= img->buf_cycle; i++)
	{
		if ((BlockSAD[i] = (int***)malloc (8 * sizeof(int**))) == NULL)
			perror ("InitializeFastFullIntegerSearch");
		for (j = 1; j < 8; j++)
		{
			if ((BlockSAD[i][j] = (int**)malloc (16 * sizeof(int*))) == NULL)
				perror ("InitializeFastFullIntegerSearch");
			for (k = 0; k < 16; k++)
			{
				if ((BlockSAD[i][j][k] = (int*)malloc (max_pos * sizeof(int))) == NULL)
					perror ("InitializeFastFullIntegerSearch");
			}
		}
	}

	if ((search_setup_done = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL)
	  perror ("InitializeFastFullIntegerSearch");
	if ((search_center_x = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL)
	  perror ("InitializeFastFullIntegerSearch");
	if ((search_center_y = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL)
	  perror ("InitializeFastFullIntegerSearch");
	if ((pos_00 = (int*)malloc ((img->buf_cycle+1)*sizeof(int)))==NULL)
	  perror ("InitializeFastFullIntegerSearch");
}



/*****
 ***** function for deleting the arrays for fast integer motion estimation
 *****
 */
void
ClearFastFullIntegerSearch ()
{
	int  i, j, k;

	for (i = 0; i <= img->buf_cycle; i++)
	{
		for (j = 1; j < 8; j++)
		{
			for (k = 0; k < 16; k++)
			{
				free (BlockSAD[i][j][k]);
			}
			free (BlockSAD[i][j]);
		}
		free (BlockSAD[i]);
	}
	free (BlockSAD);
}



/*****
 *****  function resetting flags for fast integer motion estimation
 *****  (have to be called in start_macroblock())
 */
void
ResetFastFullIntegerSearch ()
{
	int i;
	for (i = 0; i <= img->buf_cycle; i++)
		search_setup_done [i] = 0;
}



/*****
 *****  calculation of SAD for larger blocks on the basis of 4x4 blocks
 *****
 */
void
SetupLargerBlocks (int refindex, int max_pos)
{
#define	ADD_UP_BLOCKS()		_o=*_bo; _i=*_bi; _j=*_bj; for(pos=0;pos<max_pos;pos++) *_o++ = *_i++ + *_j++;
#define	INCREMENT(inc)		_bo+=inc; _bi+=inc; _bj+=inc;

	int    pos, **_bo, **_bi, **_bj;
	register int *_o,   *_i,   *_j;

	/*--- blocktype 6 ---*/
	_bo = BlockSAD[refindex][6];
	_bi = BlockSAD[refindex][7];
	_bj = _bi + 4;
	ADD_UP_BLOCKS(); INCREMENT(1);
	ADD_UP_BLOCKS(); INCREMENT(1);
	ADD_UP_BLOCKS(); INCREMENT(1);
	ADD_UP_BLOCKS(); INCREMENT(5);
	ADD_UP_BLOCKS(); INCREMENT(1);
	ADD_UP_BLOCKS(); INCREMENT(1);
	ADD_UP_BLOCKS(); INCREMENT(1);
	ADD_UP_BLOCKS();

	/*--- blocktype 5 ---*/
	_bo = BlockSAD[refindex][5];
	_bi = BlockSAD[refindex][7];
	_bj = _bi + 1;
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS();

	/*--- blocktype 4 ---*/
	_bo = BlockSAD[refindex][4];
	_bi = BlockSAD[refindex][6];
	_bj = _bi + 1;
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS(); INCREMENT(6);
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS();

	/*--- blocktype 3 ---*/
	_bo = BlockSAD[refindex][3];
	_bi = BlockSAD[refindex][4];
	_bj = _bi + 8;
	ADD_UP_BLOCKS(); INCREMENT(2);
	ADD_UP_BLOCKS();

	/*--- blocktype 2 ---*/
	_bo = BlockSAD[refindex][2];
	_bi = BlockSAD[refindex][4];
	_bj = _bi + 2;
	ADD_UP_BLOCKS(); INCREMENT(8);
	ADD_UP_BLOCKS();

	/*--- blocktype 1 ---*/
	_bo = BlockSAD[refindex][1];
	_bi = BlockSAD[refindex][3];
	_bj = _bi + 2;
	ADD_UP_BLOCKS();
}



/*****
 ***** calculation of all SAD's (for all motion vectors and 4x4 blocks)
 *****
 */
void
SetupFastFullIntegerSearch (int      refframe,
							int    **refFrArr,
							int   ***tmp_mv,
						    int *****img_mv,
						    pel_t   *CurrRefPic,
							int	     search_range,
							int      backward,
							int	     rdopt)
// Note: All Vectors in this function are full pel only.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -