📄 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 <stdlib.h>
#include <math.h>
#include <limits.h>
#include <string.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"
// 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"
// 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];
void SetMotionVectorPredictor (short pmv[2],
char **refPic,
short ***tmp_mv,
short ref_frame,
int list,
int block_x,
int block_y,
int blockshape_x,
int blockshape_y);
extern ColocatedParams *Co_located;
extern const short block_type_shift_factor[8];
/*!
************************************************************************
* \brief
* Set motion vector predictor
************************************************************************
*/
void SetMotionVectorPredictor (short pmv[2],
char **refPic,
short ***tmp_mv,
short ref_frame,
int list,
int block_x,
int block_y,
int blockshape_x,
int blockshape_y)
{
int mb_x = 4*block_x;
int mb_y = 4*block_y;
int mb_nr = img->current_mb_nr;
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;
getLuma4x4Neighbour(mb_nr, mb_x - 1, mb_y, &block_a);
getLuma4x4Neighbour(mb_nr, mb_x, mb_y - 1, &block_b);
getLuma4x4Neighbour(mb_nr, mb_x + blockshape_x, mb_y - 1, &block_c);
getLuma4x4Neighbour(mb_nr, mb_x - 1, mb_y - 1, &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 (img->mb_data[img->current_mb_nr].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 (img->mb_data[img->current_mb_nr].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
? tmp_mv[block_b.pos_y][block_b.pos_x][hv]
: tmp_mv[block_b.pos_y][block_b.pos_x][hv] / 2
: 0;
mv_c = block_c.available ? img->mb_data[block_c.mb_addr].mb_field
? tmp_mv[block_c.pos_y][block_c.pos_x][hv]
: tmp_mv[block_c.pos_y][block_c.pos_x][hv] / 2
: 0;
}
else
{
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] * 2
: tmp_mv[block_a.pos_y][block_a.pos_x][hv]
: 0;
mv_b = block_b.available ? img->mb_data[block_b.mb_addr].mb_field
? tmp_mv[block_b.pos_y][block_b.pos_x][hv] * 2
: tmp_mv[block_b.pos_y][block_b.pos_x][hv]
: 0;
mv_c = block_c.available ? img->mb_data[block_c.mb_addr].mb_field
? tmp_mv[block_c.pos_y][block_c.pos_x][hv] * 2
: tmp_mv[block_c.pos_y][block_c.pos_x][hv]
: 0;
}
}
switch (mvPredType)
{
case MVPRED_MEDIAN:
if(!(block_b.available || block_c.available))
{
pred_vec = mv_a;
}
else
{
pred_vec = mv_a+mv_b+mv_c-imin(mv_a,imin(mv_b,mv_c))-imax(mv_a,imax(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;
}
pmv[hv] = pred_vec;
}
}
/*!
************************************************************************
* \brief
* Initialize the motion search
************************************************************************
*/
void
Init_Motion_Search_Module ()
{
int bits, i_min, i_max, k;
int i, l;
int search_range = input->search_range;
int max_search_points = imax(9, (2*search_range+1)*(2*search_range+1));
int max_ref_bits = 1 + 2 * (int)floor(log(imax(16,img->max_num_references+1)) / log(2) + 1e-10);
int max_ref = (1<<((max_ref_bits>>1)+1))-1;
int number_of_subpel_positions = 4 * (2*search_range+3);
int max_mv_bits = 3 + 2 * (int)ceil (log(number_of_subpel_positions+1) / log(2) + 1e-10);
max_mvd = (1<<( max_mv_bits >>1) )-1;
byte_abs_range = (img->max_imgpel_value > img->max_imgpel_value_uv) ? (img->max_imgpel_value + 1) * 64 : (img->max_imgpel_value_uv + 1) * 64;
//===== CREATE ARRAYS =====
//-----------------------------
if ((spiral_search_x = (short*)calloc(max_search_points, sizeof(short))) == NULL)
no_mem_exit("Init_Motion_Search_Module: spiral_search_x");
if ((spiral_search_y = (short*)calloc(max_search_points, sizeof(short))) == NULL)
no_mem_exit("Init_Motion_Search_Module: spiral_search_y");
if ((spiral_hpel_search_x = (short*)calloc(max_search_points, sizeof(short))) == NULL)
no_mem_exit("Init_Motion_Search_Module: spiral_hpel_search_x");
if ((spiral_hpel_search_y = (short*)calloc(max_search_points, sizeof(short))) == NULL)
no_mem_exit("Init_Motion_Search_Module: spiral_hpel_search_y");
if ((mvbits = (int*)calloc(2*max_mvd+1, sizeof(int))) == NULL)
no_mem_exit("Init_Motion_Search_Module: mvbits");
if ((refbits = (int*)calloc(max_ref, sizeof(int))) == NULL)
no_mem_exit("Init_Motion_Search_Module: refbits");
if ((byte_abs = (int*)calloc(byte_abs_range, sizeof(int))) == NULL)
no_mem_exit("Init_Motion_Search_Module: byte_abs");
if (img->max_num_references)
get_mem4Dint (&motion_cost, 8, 2, img->max_num_references, 4);
//--- set array offsets ---
mvbits += max_mvd;
byte_abs += byte_abs_range/2;
//===== INIT ARRAYS =====
//---------------------------
//--- init array: motion vector bits ---
mvbits[0] = 1;
for (bits=3; bits<=max_mv_bits; bits+=2)
{
i_max = 1 << (bits >> 1);
i_min = i_max >> 1;
for (i = i_min; i < i_max; i++)
mvbits[-i] = mvbits[i] = bits;
}
//--- init array: reference frame bits ---
refbits[0] = 1;
for (bits=3; bits<=max_ref_bits; bits+=2)
{
i_max = (1 << ((bits >> 1) + 1)) - 1;
i_min = i_max >> 1;
for (i = i_min; i < i_max; i++)
refbits[i] = bits;
}
//--- init array: absolute value ---
byte_abs[0] = 0;
// Set scaler for integer/subpel motion refinement.
// Currently only EPZS supports subpel positions
for (i=1; i<byte_abs_range/2; i++)
{
byte_abs[i] = byte_abs[-i] = i;
}
//--- init array: search pattern ---
spiral_search_x[0] = spiral_search_y[0] = 0;
spiral_hpel_search_x[0] = spiral_hpel_search_y[0] = 0;
for (k=1, l=1; l <= imax(1,search_range); l++)
{
for (i=-l+1; i< l; i++)
{
spiral_search_x[k] = i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -