www.pudn.com > lencod.rar > mv-search.c
/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2003, Advanced Audio Video Coding Standard, Part II
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the users without any
* license fee or royalty on an "as is" basis. The AVS disclaims
* any and all warranties, whether express, implied, or statutory,
* including any implied warranties of merchantability or of fitness
* for a particular purpose. In no event shall the contributors or
* the AVS be liable for any incidental, punitive, or consequential
* damages of any kind whatsoever arising from the use of this program.
*
* This disclaimer of warranty extends to the user of this program
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The AVS does not represent or warrant that the program furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy is available from the AVS Web site at
* http://www.avs.org.cn
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
************************************************************************
*/
/*
*************************************************************************************
* File name:
* Function:
*
*************************************************************************************
*/
#include "contributors.h"
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include "global.h"
#include "mv-search.h"
#include "refbuf.h"
#include "memalloc.h"
#include "block.h"
#ifdef FastME
#include "fast_me.h"
#endif
// These procedure pointers are used by motion_search() and one_eigthpel()
static pel_t (*PelY_14) (pel_t**, int, int);
static pel_t *(*PelYline_11) (pel_t *, int, int);
// Statistics, temporary
int max_mvd;
int* spiral_search_x;
int* spiral_search_y;
int* mvbits;
int* refbits;
int* byte_abs;
int*** motion_cost;
int*** motion_cost_bid;
#define MEDIAN(a,b,c) (a + b + c - min(a, min(b, c)) - max(a, max(b, c))); //jlzheng 6.30
/*
******************************************************************************
* Function: calculated field or frame distance between current field(frame)
* and the reference field(frame).
* Input:
* Output:
* Return:
* Attention:
* Author: Yulj 2004.07.14
******************************************************************************
*/
int calculate_distance(int blkref, int fw_bw ) //fw_bw>=: forward prediction.
{
int distance=1;
//if( img->picture_structure == 1 ) // frame
if ( img->top_bot == -1 ) // frame
{
if ( img->type == INTER_IMG ) // P img
{
if(blkref==0)
distance = img->tr*2 - img->imgtr_last_P_frm*2 ;
else if(blkref==1)
distance = img->tr*2 - img->imgtr_last_prev_P_frm*2;
else
{
assert(0); //only two reference pictures for P frame
}
}
else //B_IMG
{
if (fw_bw >=0 ) //forward
distance = img->tr*2 - img->imgtr_last_P_frm*2;
else
distance = img->imgtr_next_P_frm*2 - img->tr*2;
}
}
//else if( !progressive_sequence )
//else if( ! img->picture_structure )
else // field
{
if(img->type==INTER_IMG)
{
if(img->top_bot==0) //top field
{
switch ( blkref )
{
case 0:
distance = img->tr*2 - img->imgtr_last_P_frm*2 - 1 ;
break;
case 1:
distance = img->tr*2 - img->imgtr_last_P_frm*2 ;
break;
case 2:
distance = img->tr*2 - img->imgtr_last_prev_P_frm*2 - 1;
break;
case 3:
distance = img->tr*2 - img->imgtr_last_prev_P_frm*2 ;
break;
}
}
else if(img->top_bot==1) // bottom field.
{
switch ( blkref )
{
case 0:
distance = 1 ;
break;
case 1:
distance = img->tr*2 - img->imgtr_last_P_frm*2 ;
break;
case 2:
distance = img->tr*2 - img->imgtr_last_P_frm*2 + 1;
break;
case 3:
distance = img->tr*2 - img->imgtr_last_prev_P_frm*2 ;
break;
}
}
else
{
printf("Error. frame picture should not run into this branch.");
exit(-1);
}
}
else if(img->type==B_IMG)
{
assert(blkref==0 || blkref == 1);
if (fw_bw >= 0 ) //forward
{
if(img->top_bot==0) //top field
{
switch ( blkref )
{
case 0:
distance = img->tr*2 - img->imgtr_last_P_frm*2 - 1 ;
break;
case 1:
distance = img->tr*2 - img->imgtr_last_P_frm*2;
break;
}
}
else if(img->top_bot==1) // bottom field.
{
switch ( blkref )
{
case 0:
distance = img->tr*2 - img->imgtr_last_P_frm*2 ;
break;
case 1:
distance = img->tr*2 - img->imgtr_last_P_frm*2 + 1;
break;
}
}
else
{
printf("Error. frame picture should not run into this branch.");
exit(-1);
}
}
else // backward
{
if(img->top_bot==0) //top field
{
switch ( blkref )
{
case 0:
distance = img->imgtr_next_P_frm*2 - img->tr*2;
break;
case 1:
distance = img->imgtr_next_P_frm*2 - img->tr*2 + 1;
break;
}
}
else if(img->top_bot==1) // bottom field.
{
switch ( blkref )
{
case 0:
distance = img->imgtr_next_P_frm*2 - img->tr*2 - 1;
break;
case 1:
distance = img->imgtr_next_P_frm*2 - img->tr*2 ;
break;
}
}
else
{
printf("Error. frame picture should not run into this branch.");
exit(-1);
}
}
}
}
return distance;
}
/*Lou 1016 End*/
/*Lou 1016 Start*/
//The unit of time distance is calculated by field time
/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int scale_motion_vector(int motion_vector, int currblkref, int neighbourblkref, int currsmbtype, int neighboursmbtype, int block_y_pos, int curr_block_y, int ref, int direct_mv)
{
int neighbour_coding_stage = -2;
int current_coding_stage = -2;
int sign = (motion_vector>0?1:-1);
int mult_distance;
int devide_distance;
motion_vector = abs(motion_vector);
if(motion_vector == 0)
return 0;
//!!!--- Yulj 2004.07.15
// The better way is to deinfe ref_frame same as index in motion search function.
// ref_frame is different from index when it is B field back ward prediction.
// change ref_frame to index for backwward prediction of B field.
// ref_frame : 1 | 0 | -2 | -1
// index: 1 | 0 | 0 | 1
// direction: f | f | b | b
if ( img->type == B_IMG &amt;&amt; !img->picture_structure &amt;&amt; ref < 0 )
{
currblkref = 1 - currblkref;
neighbourblkref = 1 - neighbourblkref;
}
//---end
mult_distance = calculate_distance(currblkref, ref);
devide_distance = calculate_distance(neighbourblkref, ref);
motion_vector = sign*((motion_vector*mult_distance*(512/devide_distance)+256)>>9);
// motion_vector = ((motion_vector * mult_distance * (512 / devide_distance) + 256) >> 9 );
return motion_vector;
}
/*Lou 1016 End*/
/*
*************************************************************************
* Function:setting the motion vector predictor
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void SetMotionVectorPredictor (int pmv[2],
int **refFrArr,
int ***tmp_mv,
int ref_frame,
int mb_pix_x,
int mb_pix_y,
int blockshape_x,
int blockshape_y,//Lou 1016
int ref,
int direct_mv)//Lou 1016
{
int pic_block_x = (img->block_x>>1) + (mb_pix_x>>3);
int pic_block_y = (img->block_y>>1) + (mb_pix_y>>3);
int mb_nr = img->current_mb_nr;
int mb_width = img->width/16;
int mb_available_up = (img->mb_y == 0 ) ? 0 : (img->mb_data[mb_nr].slice_nr == img->mb_data[mb_nr-mb_width ].slice_nr); //jlzheng 6.23
int mb_available_left = (img->mb_x == 0 ) ? 0 : (img->mb_data[mb_nr].slice_nr == img->mb_data[mb_nr-1 ].slice_nr); // jlzheng 6.23
int mb_available_upleft = (img->mb_x == 0 ||
img->mb_y == 0 ) ? 0 : (img->mb_data[mb_nr].slice_nr == img->mb_data[mb_nr-mb_width-1].slice_nr);
int mb_available_upright = (img->mb_x >= mb_width-1 ||
img->mb_y == 0 ) ? 0 : (img->mb_data[mb_nr].slice_nr == img->mb_data[mb_nr-mb_width+1].slice_nr);
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;
int mva[3] , mvb[3],mvc[3];
/*lgp*/
int y_up = 1,y_upright=1,y_upleft=1,off_y=0;
/*Lou 1016 Start*/
int rFrameUL;
Macroblock* currMB = &amt;img->mb_data[img->current_mb_nr];
int smbtypecurr, smbtypeL, smbtypeU, smbtypeUL, smbtypeUR;
smbtypecurr = -2;
smbtypeL = -2;
smbtypeU = -2;
smbtypeUL = -2;
smbtypeUR = -2;
/*Lou 1016 End*/
/* 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_pix_y > 0);
block_available_left = mb_available_left || (mb_pix_x > 0);
if (mb_pix_y > 0)
{
if (mb_pix_x < 8) // first column of 8x8 blocks
{
if (mb_pix_y==8)
{
if (blockshape_x == 16)
block_available_upright = 0;
else
block_available_upright = 1;
}
else
{
if (mb_pix_x+blockshape_x != 8)
block_available_upright = 1;
else
block_available_upright = 0;
}
}
else
{
if (mb_pix_x+blockshape_x != 16)
block_available_upright = 1;
else
block_available_upright = 0;
}
}
else if (mb_pix_x+blockshape_x != MB_BLOCK_SIZE)
{
block_available_upright = block_available_up;
}
else
{
block_available_upright = mb_available_upright;
}
if (mb_pix_x > 0)
{
block_available_upleft = (mb_pix_y > 0 ? 1 : block_available_up);
}
else if (mb_pix_y > 0)
{
block_available_upleft = block_available_left;
}
else
{
block_available_upleft = mb_available_upleft;
}
/*Lou 1016 Start*/
mvPredType = MVPRED_MEDIAN;
rFrameL = block_available_left ? refFrArr[pic_block_y -off_y/*lgp*/] [pic_block_x-1] : -1;
rFrameU = block_available_up ? refFrArr[pic_block_y-/*1*/y_up/*lgp*/][pic_block_x] : -1;
rFrameUR = block_available_upright ? refFrArr[pic_block_y-/*1*/y_upright/*lgp*/][pic_block_x+blockshape_x/8] :
block_available_upleft ? refFrArr[pic_block_y-/*1*/y_upleft/*lgp*/][pic_block_x-1] : -1;
rFrameUL = block_available_upleft ? refFrArr[pic_block_y-/*1*/y_upleft/*lgp*/][pic_block_x-1] : -1;
if((rFrameL != -1)&amt;&amt;(rFrameU == -1)&amt;&amt;(rFrameUR == -1))
mvPredType = MVPRED_L;
else if((rFrameL == -1)&amt;&amt;(rFrameU != -1)&amt;&amt;(rFrameUR == -1))
mvPredType = MVPRED_U;
else if((rFrameL == -1)&amt;&amt;(rFrameU == -1)&amt;&amt;(rFrameUR != -1))
mvPredType = MVPRED_UR;
/*Lou 1016 End*/
else if(blockshape_x == 8 &amt;&amt; blockshape_y == 16)
{
if(mb_pix_x == 0)
{
if(rFrameL == ref_frame)
mvPredType = MVPRED_L;
}
else
{
if(rFrameUR == ref_frame)
mvPredType = MVPRED_UR;
}
}
//#endif
else if(blockshape_x == 16 &amt;&amt; blockshape_y == 8)
{
if(mb_pix_y == 0)
{
if(rFrameU == ref_frame)
mvPredType = MVPRED_U;
}
else
{
if(rFrameL == ref_frame)
mvPredType = MVPRED_L;
}
}
for (hv=0; hv < 2; hv++)
{
mva[hv] = mv_a = block_available_left ? tmp_mv[hv][pic_block_y - off_y/*lgp*/][4+pic_block_x-1] : 0;
mvb[hv] = mv_b = block_available_up ? tmp_mv[hv][pic_block_y-/*1*/y_up/*lgp*/][4+pic_block_x] : 0;
mv_d = block_available_upleft ? tmp_mv[hv][pic_block_y-/*1*/y_upleft/*lgp*/][4+pic_block_x-1] : 0;
mvc[hv] = mv_c = block_available_upright ? tmp_mv[hv][pic_block_y-/*1*/y_upright/*lgp*/][4+pic_block_x+blockshape_x/8] : mv_d;
//--- Yulj 2004.07.04
// mv_a, mv_b... are not scaled.
mva[hv] = scale_motion_vector(mva[hv], ref_frame, rFrameL, smbtypecurr, smbtypeL, pic_block_y-off_y, pic_block_y, ref, direct_mv);
mvb[hv] = scale_motion_vector(mvb[hv], ref_frame, rFrameU, smbtypecurr, smbtypeU, pic_block_y-y_up, pic_block_y, ref, direct_mv);
mv_d = scale_motion_vector(mv_d, ref_frame, rFrameUL, smbtypecurr, smbtypeUL, pic_block_y-y_upleft, pic_block_y, ref, direct_mv);
mvc[hv] = block_available_upright ? scale_motion_vector(mvc[hv], ref_frame, rFrameUR, smbtypecurr, smbtypeUR, pic_block_y-y_upright, pic_block_y, ref, direct_mv): mv_d;
switch (mvPredType)
{
case MVPRED_MEDIAN:
if(hv == 1){
// jlzheng 7.2
// !! for A
//
mva[2] = abs(mva[0] - mvb[0]) + abs(mva[1] - mvb[1]) ;
// !! for B
//
mvb[2] = abs(mvb[0] - mvc[0]) + abs(mvb[1] - mvc[1]);
// !! for C
//
mvc[2] = abs(mvc[0] - mva[0]) + abs(mvc[1] - mva[1]) ;
pred_vec = MEDIAN(mva[2],mvb[2],mvc[2]);
if(pred_vec == mva[2]){
pmv[0] = mvc[0];
pmv[1] = mvc[1];
}
else if(pred_vec == mvb[2]){
pmv[0] = mva[0];
pmv[1] = mva[1];
}
else {
pmv[0] = mvb[0];
pmv[1] = mvb[1];
}// END
}
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;
}
if(mvPredType != MVPRED_MEDIAN)
pmv[hv] = pred_vec;
}
}
/*
*************************************************************************
* Function:Initialize the motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void Init_Motion_Search_Module ()
{
int bits, i, imin, imax, k, l;
int search_range = input->search_range;
int number_of_reference_frames = img->buf_cycle;
int max_search_points = (2*search_range+1)*(2*search_range+1);
int max_ref_bits = 1 + 2 * (int)floor(log(max(16,number_of_reference_frames+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;
//===== CREATE ARRAYS =====
//-----------------------------
if ((spiral_search_x = (int*)calloc(max_search_points, sizeof(int))) == NULL)
no_mem_exit("Init_Motion_Search_Module: spiral_search_x");
if ((spiral_search_y = (int*)calloc(max_search_points, sizeof(int))) == NULL)
no_mem_exit("Init_Motion_Search_Module: spiral_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(512, sizeof(int))) == NULL)
no_mem_exit("Init_Motion_Search_Module: byte_abs");
get_mem3Dint (&amt;motion_cost, 8, 2*(img->buf_cycle+1), 4);
get_mem3Dint (&amt;motion_cost_bid, 8, 2*(img->buf_cycle+1), 4);
//--- set array offsets ---
mvbits += max_mvd;
byte_abs += 256;
//===== INIT ARRAYS =====
//---------------------------
//--- init array: motion vector bits ---
mvbits[0] = 1;
for (bits=3; bits<=max_mv_bits; bits+=2)
{
imax = 1 << (bits >> 1);
imin = imax >> 1;
for (i = imin; i < imax; i++)
mvbits[-i] = mvbits[i] = bits;
}
//--- init array: reference frame bits ---
refbits[0] = 1;
for (bits=3; bits<=max_ref_bits; bits+=2)
{
imax = (1 << ((bits >> 1) + 1)) - 1;
imin = imax >> 1;
for (i = imin; i < imax; i++)
refbits[i] = bits;
}
//--- init array: absolute value ---
byte_abs[0] = 0;
for (i=1; i<256; i++)
byte_abs[i] = byte_abs[-i] = i;
//--- init array: search pattern ---
spiral_search_x[0] = spiral_search_y[0] = 0;
for (k=1, l=1; l<=max(1,search_range); l++)
{
for (i=-l+1; i< l; i++)
{
spiral_search_x[k] = i; spiral_search_y[k++] = -l;
spiral_search_x[k] = i; spiral_search_y[k++] = l;
}
for (i=-l; i<=l; i++)
{
spiral_search_x[k] = -l; spiral_search_y[k++] = i;
spiral_search_x[k] = l; spiral_search_y[k++] = i;
}
}
}
/*
*************************************************************************
* Function:Free memory used by motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void Clear_Motion_Search_Module ()
{
//--- correct array offset ---
mvbits -= max_mvd;
byte_abs -= 256;
//--- delete arrays ---
free (spiral_search_x);
free (spiral_search_y);
free (mvbits);
free (refbits);
free (byte_abs);
free_mem3Dint (motion_cost, 8);
}
/*
*************************************************************************
* Function:Full pixel block motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int // ==> minimum motion cost after search
FullPelBlockMotionSearch (pel_t** orig_pic, // <-- original pixel values for the AxB block
int ref, // <-- reference frame (0... or -1 (backward))
int pic_pix_x, // <-- absolute x-coordinate of regarded AxB block
int pic_pix_y, // <-- absolute y-coordinate of regarded AxB block
int blocktype, // <-- block type (1-16x16 ... 7-4x4)
int pred_mv_x, // <-- motion vector predictor (x) in sub-pel units
int pred_mv_y, // <-- motion vector predictor (y) in sub-pel units
int* mv_x, // <--> in: search center (x) / out: motion vector (x) - in pel units
int* mv_y, // <--> in: search center (y) / out: motion vector (y) - in pel units
int search_range, // <-- 1-d search range in pel units
int min_mcost, // <-- minimum motion cost (cost for center or huge value)
double lambda) // <-- lagrangian parameter for determining motion cost
{
int pos, cand_x, cand_y, y, x8, mcost;
pel_t *orig_line, *ref_line;
pel_t *(*get_ref_line)(int, pel_t*, int, int);
pel_t* ref_pic = img->type==B_IMG? Refbuf11 [/*ref+((mref==mref_fld)) +1*/ref+(!img->picture_structure) +1/*by oliver 0511*/] : Refbuf11[ref];
int best_pos = 0; // position with minimum motion cost
int max_pos = (2*search_range+1)*(2*search_range+1); // number of search positions
int lambda_factor = LAMBDA_FACTOR (lambda); // factor for determining lagragian motion cost
int blocksize_y = input->blc_size[blocktype][1]; // vertical block size
int blocksize_x = input->blc_size[blocktype][0]; // horizontal block size
int blocksize_x8 = blocksize_x >> 3; // horizontal block size in 4-pel units
int pred_x = (pic_pix_x << 2) + pred_mv_x; // predicted position x (in sub-pel units)
int pred_y = (pic_pix_y << 2) + pred_mv_y; // predicted position y (in sub-pel units)
int center_x = pic_pix_x + *mv_x; // center position x (in pel units)
int center_y = pic_pix_y + *mv_y; // center position y (in pel units)
int check_for_00 = (blocktype==1 &amt;&amt; !input->rdopt &amt;&amt; img->type!=B_IMG &amt;&amt; ref==0);
int height = img->height;/*lgp*/
//===== set function for getting reference picture lines =====
if ((center_x > search_range) &amt;&amt; (center_x < img->width -1-search_range-blocksize_x) &amt;&amt;
(center_y > search_range) &amt;&amt; (center_y < height-1-search_range-blocksize_y) )
{
get_ref_line = FastLineX;
}
else
{
get_ref_line = UMVLineX;
}
//===== loop over all search positions =====
for (pos=0; pos<max_pos; pos++)
{
//--- set candidate position (absolute position in pel units) ---
cand_x = center_x + spiral_search_x[pos];
cand_y = center_y + spiral_search_y[pos];
//--- initialize motion cost (cost for motion vector) and check ---
mcost = MV_COST (lambda_factor, 2, cand_x, cand_y, pred_x, pred_y);
if (check_for_00 &amt;&amt; cand_x==pic_pix_x &amt;&amt; cand_y==pic_pix_y)
{
mcost -= WEIGHTED_COST (lambda_factor, 16);
}
if (mcost >= min_mcost)
continue;
//--- add residual cost to motion cost ---
for (y=0; y<blocksize_y; y++)
{
ref_line = get_ref_line (blocksize_x, ref_pic, cand_y+y, cand_x);
orig_line = orig_pic [y];
for (x8=0; x8<blocksize_x8; x8++)
{
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
mcost += byte_abs[ *orig_line++ - *ref_line++ ];
}
if (mcost >= min_mcost)
{
break;
}
}
//--- check if motion cost is less than minimum cost ---
if (mcost < min_mcost)
{
best_pos = pos;
min_mcost = mcost;
}
}
//===== set best motion vector and return minimum motion cost =====
if (best_pos)
{
*mv_x += spiral_search_x[best_pos];
*mv_y += spiral_search_y[best_pos];
}
return min_mcost;
}
/*
*************************************************************************
* Function:Calculate SA(T)D
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int SATD (int* diff, int use_hadamard)
{
int k, satd = 0, m[16], dd, *d=diff;
if (use_hadamard)
{
/*===== hadamard transform =====*/
m[ 0] = d[ 0] + d[12];
m[ 4] = d[ 4] + d[ 8];
m[ 8] = d[ 4] - d[ 8];
m[12] = d[ 0] - d[12];
m[ 1] = d[ 1] + d[13];
m[ 5] = d[ 5] + d[ 9];
m[ 9] = d[ 5] - d[ 9];
m[13] = d[ 1] - d[13];
m[ 2] = d[ 2] + d[14];
m[ 6] = d[ 6] + d[10];
m[10] = d[ 6] - d[10];
m[14] = d[ 2] - d[14];
m[ 3] = d[ 3] + d[15];
m[ 7] = d[ 7] + d[11];
m[11] = d[ 7] - d[11];
m[15] = d[ 3] - d[15];
d[ 0] = m[ 0] + m[ 4];
d[ 8] = m[ 0] - m[ 4];
d[ 4] = m[ 8] + m[12];
d[12] = m[12] - m[ 8];
d[ 1] = m[ 1] + m[ 5];
d[ 9] = m[ 1] - m[ 5];
d[ 5] = m[ 9] + m[13];
d[13] = m[13] - m[ 9];
d[ 2] = m[ 2] + m[ 6];
d[10] = m[ 2] - m[ 6];
d[ 6] = m[10] + m[14];
d[14] = m[14] - m[10];
d[ 3] = m[ 3] + m[ 7];
d[11] = m[ 3] - m[ 7];
d[ 7] = m[11] + m[15];
d[15] = m[15] - m[11];
m[ 0] = d[ 0] + d[ 3];
m[ 1] = d[ 1] + d[ 2];
m[ 2] = d[ 1] - d[ 2];
m[ 3] = d[ 0] - d[ 3];
m[ 4] = d[ 4] + d[ 7];
m[ 5] = d[ 5] + d[ 6];
m[ 6] = d[ 5] - d[ 6];
m[ 7] = d[ 4] - d[ 7];
m[ 8] = d[ 8] + d[11];
m[ 9] = d[ 9] + d[10];
m[10] = d[ 9] - d[10];
m[11] = d[ 8] - d[11];
m[12] = d[12] + d[15];
m[13] = d[13] + d[14];
m[14] = d[13] - d[14];
m[15] = d[12] - d[15];
d[ 0] = m[ 0] + m[ 1];
d[ 1] = m[ 0] - m[ 1];
d[ 2] = m[ 2] + m[ 3];
d[ 3] = m[ 3] - m[ 2];
d[ 4] = m[ 4] + m[ 5];
d[ 5] = m[ 4] - m[ 5];
d[ 6] = m[ 6] + m[ 7];
d[ 7] = m[ 7] - m[ 6];
d[ 8] = m[ 8] + m[ 9];
d[ 9] = m[ 8] - m[ 9];
d[10] = m[10] + m[11];
d[11] = m[11] - m[10];
d[12] = m[12] + m[13];
d[13] = m[12] - m[13];
d[14] = m[14] + m[15];
d[15] = m[15] - m[14];
/*===== sum up =====*/
for (dd=diff[k=0]; k<16; dd=diff[++k])
{
satd += (dd < 0 ? -dd : dd);
}
satd >>= 1;
}
else
{
/*===== sum up =====*/
for (k = 0; k < 16; k++)
{
satd += byte_abs [diff [k]];
}
}
return satd;
}
/*
*************************************************************************
* Function:Sub pixel block motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int // ==> minimum motion cost after search
SubPelBlockMotionSearch (pel_t** orig_pic, // <-- original pixel values for the AxB block
int ref, // <-- reference frame (0... or -1 (backward))
int pic_pix_x, // <-- absolute x-coordinate of regarded AxB block
int pic_pix_y, // <-- absolute y-coordinate of regarded AxB block
int blocktype, // <-- block type (1-16x16 ... 7-4x4)
int pred_mv_x, // <-- motion vector predictor (x) in sub-pel units
int pred_mv_y, // <-- motion vector predictor (y) in sub-pel units
int* mv_x, // <--> in: search center (x) / out: motion vector (x) - in pel units
int* mv_y, // <--> in: search center (y) / out: motion vector (y) - in pel units
int search_pos2, // <-- search positions for half-pel search (default: 9)
int search_pos4, // <-- search positions for quarter-pel search (default: 9)
int min_mcost, // <-- minimum motion cost (cost for center or huge value)
double lambda // <-- lagrangian parameter for determining motion cost
)
{
int diff[16], *d;
int pos, best_pos, mcost, abort_search;
int y0, x0, ry0, rx0, ry;
int cand_mv_x, cand_mv_y;
pel_t *orig_line;
int incr = ref==-1 ? ((!img->fld_type)&amt;&amt;/*(!img->picture_structure)&amt;&amt;*/(img->type==B_IMG)) : (mref==mref_fld)&amt;&amt;(img->type==B_IMG) ; //by oliver 0511
pel_t **ref_pic;
int lambda_factor = LAMBDA_FACTOR (lambda);
int mv_shift = 0;
int check_position0 = (blocktype==1 &amt;&amt; *mv_x==0 &amt;&amt; *mv_y==0 &amt;&amt; input->hadamard &amt;&amt; !input->rdopt &amt;&amt; img->type!=B_IMG &amt;&amt; ref==0);
int blocksize_x = input->blc_size[blocktype][0];
int blocksize_y = input->blc_size[blocktype][1];
int pic4_pix_x = (pic_pix_x << 2);
int pic4_pix_y = (pic_pix_y << 2);
int max_pos_x4 = ((img->width -blocksize_x+1)<<2);
int max_pos_y4 = ((img->height-blocksize_y+1)<<2);
int min_pos2 = (input->hadamard ? 0 : 1);
int max_pos2 = (input->hadamard ? max(1,search_pos2) : search_pos2);
int curr_diff[MB_BLOCK_SIZE][MB_BLOCK_SIZE]; // for AVS 8x8 SATD calculation
int xx,yy,kk; // indicees for curr_diff
if (!img->picture_structure)
{
if (img->type==B_IMG)
{
incr = 2;
}
}else
{
if(img->type==B_IMG)
incr = 1;
}
ref_pic = img->type==B_IMG? mref [ref+incr] : mref [ref];
/*********************************
***** *****
***** HALF-PEL REFINEMENT *****
***** *****
*********************************/
//===== convert search center to quarter-pel units =====
*mv_x <<= 2;
*mv_y <<= 2;
//===== set function for getting pixel values =====
if ((pic4_pix_x + *mv_x > 1) &amt;&amt; (pic4_pix_x + *mv_x < max_pos_x4 - 2) &amt;&amt;
(pic4_pix_y + *mv_y > 1) &amt;&amt; (pic4_pix_y + *mv_y < max_pos_y4 - 2) )
{
PelY_14 = FastPelY_14;
}
else
{
PelY_14 = UMVPelY_14;
}
//===== loop over search positions =====
for (best_pos = 0, pos = min_pos2; pos < max_pos2; pos++)
{
cand_mv_x = *mv_x + (spiral_search_x[pos] << 1); // quarter-pel units
cand_mv_y = *mv_y + (spiral_search_y[pos] << 1); // quarter-pel units
//----- set motion vector cost -----
mcost = MV_COST (lambda_factor, mv_shift, cand_mv_x, cand_mv_y, pred_mv_x, pred_mv_y);
if (check_position0 &amt;&amt; pos==0)
{
mcost -= WEIGHTED_COST (lambda_factor, 16);
}
//----- add up SATD -----
for (y0=0, abort_search=0; y0<blocksize_y &amt;&amt; !abort_search; y0+=4)
{
ry0 = ((pic_pix_y+y0)<<2) + cand_mv_y;
for (x0=0; x0<blocksize_x; x0+=4)
{
rx0 = ((pic_pix_x+x0)<<2) + cand_mv_x;
d = diff;
orig_line = orig_pic [y0 ]; ry=ry0;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d++ = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
orig_line = orig_pic [y0+1]; ry=ry0+4;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d++ = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
orig_line = orig_pic [y0+2]; ry=ry0+8;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d++ = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
orig_line = orig_pic [y0+3]; ry=ry0+12;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
for (yy=y0,kk=0; yy<y0+4; yy++)
for (xx=x0; xx<x0+4; xx++, kk++)
curr_diff[yy][xx] = diff[kk];
}
}
mcost += find_sad_8x8(input->hadamard, blocksize_x, blocksize_y, 0, 0, curr_diff);
if (mcost < min_mcost)
{
min_mcost = mcost;
best_pos = pos;
}
}
if (best_pos)
{
*mv_x += (spiral_search_x [best_pos] << 1);
*mv_y += (spiral_search_y [best_pos] << 1);
}
/************************************
***** *****
***** QUARTER-PEL REFINEMENT *****
***** *****
************************************/
//===== set function for getting pixel values =====
if ((pic4_pix_x + *mv_x > 1) &amt;&amt; (pic4_pix_x + *mv_x < max_pos_x4 - 1) &amt;&amt;
(pic4_pix_y + *mv_y > 1) &amt;&amt; (pic4_pix_y + *mv_y < max_pos_y4 - 1) )
{
PelY_14 = FastPelY_14;
}
else
{
PelY_14 = UMVPelY_14;
}
//===== loop over search positions =====
for (best_pos = 0, pos = 1; pos < search_pos4; pos++)
{
cand_mv_x = *mv_x + spiral_search_x[pos]; // quarter-pel units
cand_mv_y = *mv_y + spiral_search_y[pos]; // quarter-pel units
//----- set motion vector cost -----
mcost = MV_COST (lambda_factor, mv_shift, cand_mv_x, cand_mv_y, pred_mv_x, pred_mv_y);
//----- add up SATD -----
for (y0=0, abort_search=0; y0<blocksize_y &amt;&amt; !abort_search; y0+=4)
{
ry0 = ((pic_pix_y+y0)<<2) + cand_mv_y;
for (x0=0; x0<blocksize_x; x0+=4)
{
rx0 = ((pic_pix_x+x0)<<2) + cand_mv_x;
d = diff;
orig_line = orig_pic [y0 ]; ry=ry0;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d++ = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
orig_line = orig_pic [y0+1]; ry=ry0+4;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d++ = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
orig_line = orig_pic [y0+2]; ry=ry0+8;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d++ = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
orig_line = orig_pic [y0+3]; ry=ry0+12;
*d++ = orig_line[x0 ] - PelY_14 (ref_pic, ry, rx0 );
*d++ = orig_line[x0+1] - PelY_14 (ref_pic, ry, rx0+ 4);
*d++ = orig_line[x0+2] - PelY_14 (ref_pic, ry, rx0+ 8);
*d = orig_line[x0+3] - PelY_14 (ref_pic, ry, rx0+12);
for (yy=y0,kk=0; yy<y0+4; yy++)
for (xx=x0; xx<x0+4; xx++, kk++)
curr_diff[yy][xx] = diff[kk];
}
}
mcost += find_sad_8x8(input->hadamard, blocksize_x, blocksize_y, 0, 0, curr_diff);
if (mcost < min_mcost)
{
min_mcost = mcost;
best_pos = pos;
}
}
if (best_pos)
{
*mv_x += spiral_search_x [best_pos];
*mv_y += spiral_search_y [best_pos];
}
//===== return minimum motion cost =====
return min_mcost;
}
/*
*************************************************************************
* Function:Sub pixel block motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int // ==> minimum motion cost after search
SubPelBlockMotionSearch_bid (pel_t** orig_pic, // <-- original pixel values for the AxB block
int ref, // <-- reference frame (0... or -1 (backward))
int pic_pix_x, // <-- absolute x-coordinate of regarded AxB block
int pic_pix_y, // <-- absolute y-coordinate of regarded AxB block
int blocktype, // <-- block type (1-16x16 ... 7-4x4)
int pred_mv_x, // <-- motion vector predictor (x) in sub-pel units
int pred_mv_y, // <-- motion vector predictor (y) in sub-pel units
int* mv_x, // <--> in: search center (x) / out: motion vector (x) - in pel units
int* mv_y, // <--> in: search center (y) / out: motion vector (y) - in pel units
int search_pos2, // <-- search positions for half-pel search (default: 9)
int search_pos4, // <-- search positions for quarter-pel search (default: 9)
int min_mcost, // <-- minimum motion cost (cost for center or huge value)
double lambda // <-- lagrangian parameter for determining motion cost
)
{
int diff[16], *d;
int pos, best_pos, mcost, abort_search;
int y0, x0, ry0, rx0, ry;
int ry0_bid, rx0_bid, ry_bid;
int cand_mv_x, cand_mv_y;
pel_t *orig_line;
int incr = ref==-1 ? ((!img->fld_type)&amt;&amt;(mref==mref_fld)&amt;&amt;(img->type==B_IMG)) : (mref==mref_fld)&amt;&amt;(img->type==B_IMG) ;
pel_t **ref_pic,**ref_pic_bid;
int lambda_factor = LAMBDA_FACTOR (lambda);
int mv_shift = 0;
int check_position0 = (blocktype==1 &amt;&amt; *mv_x==0 &amt;&amt; *mv_y==0 &amt;&amt; input->hadamard &amt;&amt; !input->rdopt &amt;&amt; img->type!=B_IMG &amt;&amt; ref==0);
int blocksize_x = input->blc_size[blocktype][0];
int blocksize_y = input->blc_size[blocktype][1];
int pic4_pix_x = (pic_pix_x << 2);
int pic4_pix_y = (pic_pix_y << 2);
int max_pos_x4 = ((img->width -blocksize_x+1)<<2);
int max_pos_y4 = ((img->height-blocksize_y+1)<<2);
int min_pos2 = (input->hadamard ? 0 : 1);
int max_pos2 = (input->hadamard ? max(1,search_pos2) : search_pos2);
int apply_weights = 0;
int delta_P,TRp,DistanceIndexFw,DistanceIndexBw,refframe ,delta_PB;
refframe = ref;
delta_P = 2*(img->imgtr_next_P_frm - img->imgtr_last_P_frm);
if(img->picture_structure)
TRp = (refframe+1)*delta_P;
else
TRp = delta_P;//ref == 0 ? delta_P-1 : delta_P+1;
delta_PB = 2*(img->tr - img->imgtr_last_P_frm);
if(!img->picture_structure)
{
if(img->current_mb_nr_fld < img->total_number_mb) //top field
DistanceIndexFw = refframe == 0 ? delta_PB-1:delta_PB;
else
DistanceIndexFw = refframe == 0 ? delta_PB:delta_PB+1;
}
else
DistanceIndexFw = delta_PB;
DistanceIndexBw = TRp - DistanceIndexFw;
//xyji 11.23
if (!img->picture_structure)
{
if (img->type==B_IMG)
{
incr = 2;
}
}else
{
if(img->type==B_IMG)
incr = 1;
}
ref_pic = img->type==B_IMG? mref [ref+incr] : mref [ref];
ref_pic_bid = img->type==B_IMG? mref [img->picture_structure ? 0 : ref/*2 - (ref+incr)*/] : mref [ref];
/*********************************
***** *****
***** HALF-PEL REFINEMENT *****
***** *****
*********************************/
//===== convert search center to quarter-pel units =====
*mv_x <<= 2;
*mv_y <<= 2;
//===== set function for getting pixel values =====
if ((pic4_pix_x + *mv_x > 1) &amt;&amt; (pic4_pix_x + *mv_x < max_pos_x4 - 2) &amt;&amt;
(pic4_pix_y + *mv_y > 1) &amt;&amt; (pic4_pix_y + *mv_y < max_pos_y4 - 2) )
{
PelY_14 = UMVPelY_14;//FastPelY_14;//xyji
}
else
{
PelY_14 = UMVPelY_14;
}
//===== loop over search positions =====
for (best_pos = 0, pos = min_pos2; pos < max_pos2; pos++)
{
cand_mv_x = *mv_x + (spiral_search_x[pos] << 1); // quarter-pel units
cand_mv_y = *mv_y + (spiral_search_y[pos] << 1); // quarter-pel units
//----- set motion vector cost -----
mcost = MV_COST (lambda_factor, mv_shift, cand_mv_x, cand_mv_y, pred_mv_x, pred_mv_y);
if (check_position0 &amt;&amt; pos==0)
{
mcost -= WEIGHTED_COST (lambda_factor, 16);
}
//----- add up SATD -----
for (y0=0, abort_search=0; y0<blocksize_y &amt;&amt; !abort_search; y0+=4)
{
ry0 = ((pic_pix_y+y0)<<2) + cand_mv_y;
//ry0_bid = ((pic_pix_y+y0)<<2) - ((cand_mv_y*DistanceIndexBw*(256/DistanceIndexFw)+128)>>8);
ry0_bid = ((pic_pix_y+y0)<<2) - ((cand_mv_y*DistanceIndexBw*(512/DistanceIndexFw)+256)>>9);
for (x0=0; x0<blocksize_x; x0+=4)
{
rx0 = ((pic_pix_x+x0)<<2) + cand_mv_x;
//rx0_bid = ((pic_pix_x+x0)<<2) - ((cand_mv_x*DistanceIndexBw*(256/DistanceIndexFw)+128)>>8);
rx0_bid = ((pic_pix_x+x0)<<2) - ((cand_mv_x*DistanceIndexBw*(512/DistanceIndexFw)+256)>>9);
d = diff;
orig_line = orig_pic [y0 ]; ry=ry0; ry_bid = ry0_bid;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d++ = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
orig_line = orig_pic [y0+1]; ry=ry0+4;ry_bid=ry0_bid+4;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d++ = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
orig_line = orig_pic [y0+2]; ry=ry0+8;ry_bid=ry0_bid+8;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d++ = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
orig_line = orig_pic [y0+3]; ry=ry0+12;ry_bid=ry0_bid+12;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
if ((mcost += SATD (diff, input->hadamard)) > min_mcost)
{
abort_search = 1;
break;
}
}
}
if (mcost < min_mcost)
{
min_mcost = mcost;
best_pos = pos;
}
}
if (best_pos)
{
*mv_x += (spiral_search_x [best_pos] << 1);
*mv_y += (spiral_search_y [best_pos] << 1);
}
/************************************
***** *****
***** QUARTER-PEL REFINEMENT *****
***** *****
************************************/
//===== set function for getting pixel values =====
if ((pic4_pix_x + *mv_x > 1) &amt;&amt; (pic4_pix_x + *mv_x < max_pos_x4 - 1) &amt;&amt;
(pic4_pix_y + *mv_y > 1) &amt;&amt; (pic4_pix_y + *mv_y < max_pos_y4 - 1) )
{
PelY_14 = UMVPelY_14;//FastPelY_14;//xyji
}
else
{
PelY_14 = UMVPelY_14;
}
//===== loop over search positions =====
for (best_pos = 0, pos = 1; pos < search_pos4; pos++)
{
cand_mv_x = *mv_x + spiral_search_x[pos]; // quarter-pel units
cand_mv_y = *mv_y + spiral_search_y[pos]; // quarter-pel units
//----- set motion vector cost -----
mcost = MV_COST (lambda_factor, mv_shift, cand_mv_x, cand_mv_y, pred_mv_x, pred_mv_y);
//----- add up SATD -----
for (y0=0, abort_search=0; y0<blocksize_y &amt;&amt; !abort_search; y0+=4)
{
ry0 = ((pic_pix_y+y0)<<2) + cand_mv_y;
ry0_bid = ((pic_pix_y+y0)<<2) - ((cand_mv_y*DistanceIndexBw*(256/DistanceIndexFw)+128)>>8);
for (x0=0; x0<blocksize_x; x0+=4)
{
rx0 = ((pic_pix_x+x0)<<2) + cand_mv_x;
rx0_bid = ((pic_pix_x+x0)<<2) - ((cand_mv_x*DistanceIndexBw*(256/DistanceIndexFw)+128)>>8);
d = diff;
orig_line = orig_pic [y0 ]; ry=ry0; ry_bid=ry0_bid;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d++ = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
orig_line = orig_pic [y0+1]; ry=ry0+4;ry_bid=ry0_bid+4;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d++ = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
orig_line = orig_pic [y0+2]; ry=ry0+8;ry_bid=ry0_bid+8;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d++ = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
orig_line = orig_pic [y0+3]; ry=ry0+12;ry_bid=ry0_bid+12;
*d++ = orig_line[x0 ] - (PelY_14 (ref_pic, ry, rx0 ) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid ))/2;
*d++ = orig_line[x0+1] - (PelY_14 (ref_pic, ry, rx0+ 4) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 4))/2;
*d++ = orig_line[x0+2] - (PelY_14 (ref_pic, ry, rx0+ 8) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+ 8))/2;
*d = orig_line[x0+3] - (PelY_14 (ref_pic, ry, rx0+12) + PelY_14 (ref_pic_bid, ry_bid, rx0_bid+12))/2;
if ((mcost += SATD (diff, input->hadamard)) > min_mcost)
{
abort_search = 1;
break;
}
}
}
if (mcost < min_mcost)
{
min_mcost = mcost;
best_pos = pos;
}
}
if (best_pos)
{
*mv_x += spiral_search_x [best_pos];
*mv_y += spiral_search_y [best_pos];
}
//===== return minimum motion cost =====
return min_mcost;
}
/*
*************************************************************************
* Function:Block motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int // ==> minimum motion cost after search
BlockMotionSearch (int ref, // <-- reference frame (0... or -1 (backward))
int pic_pix_x, // <-- absolute x-coordinate of regarded AxB block
int pic_pix_y, // <-- absolute y-coordinate of regarded AxB block
int blocktype, // <-- block type (1-16x16 ... 7-4x4)
int search_range, // <-- 1-d search range for integer-position search
double lambda // <-- lagrangian parameter for determining motion cost
)
{
static pel_t orig_val [256];
static pel_t *orig_pic [16] = {orig_val, orig_val+ 16, orig_val+ 32, orig_val+ 48,
orig_val+ 64, orig_val+ 80, orig_val+ 96, orig_val+112,
orig_val+128, orig_val+144, orig_val+160, orig_val+176,
orig_val+192, orig_val+208, orig_val+224, orig_val+240};
int pred_mv_x, pred_mv_y, mv_x, mv_y, i, j;
int max_value = (1<<20);
int min_mcost = max_value;
int mb_pix_x = pic_pix_x-img->pix_x;
int mb_pix_y = pic_pix_y-img->pix_y;
int b8_x = (mb_pix_x>>3);
int b8_y = (mb_pix_y>>3);
int bsx = input->blc_size[blocktype][0];
int bsy = input->blc_size[blocktype][1];
int refframe = (ref==-1 ? 0 : ref);
int* pred_mv;
int** ref_array = ((img->type!=B_IMG) ? refFrArr : ref>=0 ? fw_refFrArr : bw_refFrArr);
int*** mv_array = ((img->type!=B_IMG) ? tmp_mv : ref>=0 ? tmp_fwMV : tmp_bwMV);
int***** all_bmv = img->all_bmv;
int***** all_mv = (ref/*==-1*/ <0/*lgp13*/? img->all_bmv : img->all_mv);
byte** imgY_org_pic = imgY_org;
int incr_y=1,off_y=0;/*lgp*/
int center_x = pic_pix_x;/*lgp*/
int center_y = pic_pix_y;/*lgp*/
int MaxMVHRange, MaxMVVRange;
if (!img->picture_structure) // field coding
{
if (img->type==B_IMG)
refframe = ref<0 ? ref+2 : ref;
}
pred_mv = ((img->type!=B_IMG) ? img->mv : ref>=0 ? img->p_fwMV : img->p_bwMV)[mb_pix_x>>3][mb_pix_y>>3][refframe][blocktype];
//==================================
//===== GET ORIGINAL BLOCK =====
//==================================
for (j = 0; j < bsy; j++)
{
for (i = 0; i < bsx; i++)
{
orig_pic[j][i] = imgY_org_pic[pic_pix_y+/*j*/incr_y*j+off_y/*lgp*/][pic_pix_x+i];
}
}
//===========================================
//===== GET MOTION VECTOR PREDICTOR =====
//===========================================
SetMotionVectorPredictor (pred_mv, ref_array, mv_array, refframe, mb_pix_x, mb_pix_y, bsx, bsy, ref, 0);//Lou 1016
pred_mv_x = pred_mv[0];
pred_mv_y = pred_mv[1];
//==================================
//===== INTEGER-PEL SEARCH =====
//==================================
//--- set search center ---
mv_x = pred_mv_x / 4;
mv_y = pred_mv_y / 4;
if (!input->rdopt)
{
//--- adjust search center so that the (0,0)-vector is inside ---
mv_x = max (-search_range, min (search_range, mv_x));
mv_y = max (-search_range, min (search_range, mv_y));
}
//--- perform motion search ---
min_mcost = FullPelBlockMotionSearch (orig_pic, ref, center_x/*lgp*/, center_y/*lgp*/, blocktype,
pred_mv_x, pred_mv_y, &amt;mv_x, &amt;mv_y, search_range,
min_mcost, lambda);
//==============================
//===== SUB-PEL SEARCH =====
//==============================
if (input->hadamard)
{
min_mcost = max_value;
}
min_mcost = SubPelBlockMotionSearch (orig_pic, ref, center_x/*lgp*/, center_y/*lgp*/, blocktype,
pred_mv_x, pred_mv_y, &amt;mv_x, &amt;mv_y, 9, 9,
min_mcost, lambda);
if (!input->rdopt)
{
// Get the skip mode cost
if (blocktype == 1 &amt;&amt; img->type == INTER_IMG)
{
int cost;
FindSkipModeMotionVector ();
cost = GetSkipCostMB (lambda);
cost -= (int)floor(8*lambda+0.4999);
if (cost < min_mcost)
{
min_mcost = cost;
mv_x = img->all_mv [0][0][0][0][0];
mv_y = img->all_mv [0][0][0][0][1];
}
}
}
MaxMVHRange= MAX_H_SEARCH_RANGE; //add by wuzhongmou
MaxMVVRange= MAX_V_SEARCH_RANGE;
if(!img->picture_structure) //field coding
{
MaxMVVRange=MAX_V_SEARCH_RANGE_FIELD;
}
if(mv_x < -MaxMVHRange )
mv_x = -MaxMVHRange;
if( mv_x> MaxMVHRange-1)
mv_x=MaxMVHRange-1;
if( mv_y < -MaxMVVRange)
mv_y = -MaxMVVRange;
if( mv_y > MaxMVVRange-1)
mv_y = MaxMVVRange-1; //add by wuzhongmou
//===============================================
//===== SET MV'S AND RETURN MOTION COST =====
//===============================================
for (i=0; i < (bsx>>3); i++)
{
for (j=0; j < (bsy>>3); j++)
{
all_mv[b8_x+i][b8_y+j][refframe][blocktype][0] = mv_x;
all_mv[b8_x+i][b8_y+j][refframe][blocktype][1] = mv_y;
}
}
return min_mcost;
}
/*
*************************************************************************
* Function:Block motion search
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int // ==> minimum motion cost after search
BlockMotionSearch_bid (int ref, // <-- reference frame (0... or -1 (backward))
int pic_pix_x, // <-- absolute x-coordinate of regarded AxB block
int pic_pix_y, // <-- absolute y-coordinate of regarded AxB block
int blocktype, // <-- block type (1-16x16 ... 7-4x4)
int search_range, // <-- 1-d search range for integer-position search
double lambda // <-- lagrangian parameter for determining motion cost
)
{
static pel_t orig_val [256];
static pel_t *orig_pic [16] = {orig_val, orig_val+ 16, orig_val+ 32, orig_val+ 48,
orig_val+ 64, orig_val+ 80, orig_val+ 96, orig_val+112,
orig_val+128, orig_val+144, orig_val+160, orig_val+176,
orig_val+192, orig_val+208, orig_val+224, orig_val+240};
int pred_mv_x, pred_mv_y, mv_x, mv_y, i, j;
int max_value = (1<<20);
int min_mcost = max_value;
int mb_x = pic_pix_x-img->pix_x;
int mb_y = pic_pix_y-img->pix_y;
//sw 9.30
int block_x = (mb_x>>3);
int block_y = (mb_y>>3);
int bsx = input->blc_size[blocktype][0];
int bsy = input->blc_size[blocktype][1];
int refframe = (ref==-1 ? 0 : ref);
int* pred_mv;
int** ref_array = ((img->type!=B_IMG) ? refFrArr : ref>=0 ? fw_refFrArr : bw_refFrArr);
int*** mv_array = ((img->type!=B_IMG) ? tmp_mv : ref>=0 ? tmp_fwMV : tmp_bwMV);
int***** all_bmv = img->all_bmv;
int***** all_mv = (ref==-1 ? img->all_bmv : img->all_omv);
//sw 10.1
//int***** all_mv = (ref==-1 ? img->all_bmv : img->all_mv);
byte** imgY_org_pic = imgY_org;
int incr_y=1,off_y=0;/*lgp*/
int center_x = pic_pix_x;/*lgp*/
int center_y = pic_pix_y;/*lgp*/
int MaxMVHRange, MaxMVVRange;
if (!img->picture_structure) // field coding
{
if (img->type==B_IMG)
refframe = ref<0 ? ref+2 : ref;
}
//sw 10.1
pred_mv = ((img->type!=B_IMG) ? img->mv : ref>=0 ? img->omv/*img->p_fwMV*/ : img->p_bwMV)[mb_x>>3][mb_y>>3][refframe][blocktype];
// pred_mv = ((img->type!=B_IMG) ? img->mv : ref>=0 ? img->p_fwMV: img->p_bwMV)[mb_x>>3][mb_y>>3][refframe][blocktype];
//==================================
//===== GET ORIGINAL BLOCK =====
//==================================
for (j = 0; j < bsy; j++)
{
for (i = 0; i < bsx; i++)
{
orig_pic[j][i] = imgY_org_pic[pic_pix_y+/*j*/incr_y*j+off_y/*lgp*/][pic_pix_x+i];
}
}
//===========================================
//===== GET MOTION VECTOR PREDICTOR =====
//===========================================
//SetMotionVectorPredictor (pred_mv, ref_array, mv_array, refframe, mb_x, mb_y, bsx, bsy);
SetMotionVectorPredictor (pred_mv, ref_array, mv_array, refframe, mb_x, mb_y, bsx, bsy, ref, 0);//Lou 1016
pred_mv_x = pred_mv[0];
pred_mv_y = pred_mv[1];
//==================================
//===== INTEGER-PEL SEARCH =====
//==================================
//--- set search center ---
mv_x = pred_mv_x / 4;
mv_y = pred_mv_y / 4;
if (!input->rdopt)
{
//--- adjust search center so that the (0,0)-vector is inside ---
mv_x = max (-search_range, min (search_range, mv_x));
mv_y = max (-search_range, min (search_range, mv_y));
}
//--- perform motion search ---
min_mcost = FullPelBlockMotionSearch (orig_pic, ref, center_x/*lgp*/, center_y/*lgp*/, blocktype,
pred_mv_x, pred_mv_y, &amt;mv_x, &amt;mv_y, search_range,
min_mcost, lambda);
//==============================
//===== SUB-PEL SEARCH =====
//==============================
if (input->hadamard)
{
min_mcost = max_value;
}
min_mcost = SubPelBlockMotionSearch_bid (orig_pic, ref, center_x/*lgp*/, center_y/*lgp*/, blocktype,
pred_mv_x, pred_mv_y, &amt;mv_x, &amt;mv_y, 9, 9,
min_mcost, lambda);
if (!input->rdopt)
{
// Get the skip mode cost
if (blocktype == 1 &amt;&amt; img->type == INTER_IMG)
{
int cost;
FindSkipModeMotionVector ();
cost = GetSkipCostMB (lambda);
cost -= (int)floor(8*lambda+0.4999);
if (cost < min_mcost)
{
min_mcost = cost;
mv_x = img->all_mv [0][0][0][0][0];
mv_y = img->all_mv [0][0][0][0][1];
}
}
}
MaxMVHRange= MAX_H_SEARCH_RANGE; //add by wuzhongmou
MaxMVVRange= MAX_V_SEARCH_RANGE;
if(!img->picture_structure) //field coding
{
MaxMVVRange=MAX_V_SEARCH_RANGE_FIELD;
}
if(mv_x < -MaxMVHRange )
mv_x = -MaxMVHRange;
if( mv_x> MaxMVHRange-1)
mv_x=MaxMVHRange-1;
if( mv_y < -MaxMVVRange)
mv_y = -MaxMVVRange;
if( mv_y > MaxMVVRange-1)
mv_y = MaxMVVRange-1; //add by wuzhongmou
//===============================================
//===== SET MV'S AND RETURN MOTION COST =====
//===============================================
for (i=0; i < (bsx>>3); i++)
{
for (j=0; j < (bsy>>3); j++)
{
all_mv[block_x+i][block_y+j][refframe][blocktype][0] = mv_x;
all_mv[block_x+i][block_y+j][refframe][blocktype][1] = mv_y;
}
}
return min_mcost;
}
/*
*************************************************************************
* Function:Motion Cost for Bidirectional modes
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int
BIDPartitionCost (int blocktype,
int block8x8,
int fw_ref,
int bw_ref,/*lgp*13*/
int lambda_factor)
{
static int bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
static int by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}};
int diff[16];
int pic_pix_x, block_x, block_y;
int v, h, mcost, i, j, k;
int mvd_bits = 0;
int parttype = (blocktype<4?blocktype:4);
int step_h0 = (input->blc_size[ parttype][0]>>2);
int step_v0 = (input->blc_size[ parttype][1]>>2);
int step_h = (input->blc_size[blocktype][0]>>2);
int step_v = (input->blc_size[blocktype][1]>>2);
int curr_blk[MB_BLOCK_SIZE][MB_BLOCK_SIZE]; // pred.error buffer for AVS
int bsx = min(input->blc_size[blocktype][0],8);
int bsy = min(input->blc_size[blocktype][1],8);
int incr_y=1,off_y=0;/*lgp*/
int pic_pix_y = img->pix_y + ((block8x8 / 2) << 3);/*lgp*///b
int bxx, byy; // indexing curr_blk
byte** imgY_original = imgY_org;
int *****all_mv = img->all_mv;
int *****all_bmv = img->all_bmv;
int *****p_fwMV = img->p_fwMV;
int *****p_bwMV = img->p_bwMV;
int *****all_omv = img->all_omv;
for (v=by0[parttype][block8x8]; v<by0[parttype][block8x8]+step_v0; v+=step_v)
for (h=bx0[parttype][block8x8]; h<bx0[parttype][block8x8]+step_h0; h+=step_h)
{
//sw 10.1
all_omv [h/2][v/2][fw_ref][blocktype][0] = all_mv [h/2][v/2][fw_ref][blocktype][0];
all_omv [h/2][v/2][fw_ref][blocktype][1] = all_mv [h/2][v/2][fw_ref][blocktype][1];
}
//----- cost for motion vector bits -----
for (v=by0[parttype][block8x8]; v<by0[parttype][block8x8]+step_v0; v+=step_v)
for (h=bx0[parttype][block8x8]; h<bx0[parttype][block8x8]+step_h0; h+=step_h)
{
mvd_bits += mvbits[ all_omv [h/2][v/2][fw_ref][blocktype][0] - p_fwMV[h/2][v/2][fw_ref][blocktype][0] ];
mvd_bits += mvbits[ all_omv [h/2][v/2][fw_ref][blocktype][1] - p_fwMV[h/2][v/2][fw_ref][blocktype][1] ];
}
mcost = WEIGHTED_COST (lambda_factor, mvd_bits);
//----- cost of residual signal -----
for (byy=0, v=by0[parttype][block8x8]; v<by0[parttype][block8x8]+step_v0; byy+=4, v++)
{
//pic_pix_y = pix_y + (block_y = (v<<2));/*lgp*///b
block_y = (v<<2);/*lgp*///b
for (bxx=0, h=bx0[parttype][block8x8]; h<bx0[parttype][block8x8]+step_h0; bxx+=4, h++)
{
pic_pix_x = img->pix_x + (block_x = (h<<2));
LumaPrediction4x4 (block_x, block_y, blocktype, blocktype, fw_ref, bw_ref);/*lgp*13*/
for (k=j=0; j<4; j++)
for ( i=0; i<4; i++, k++)
{
diff[k] = curr_blk[byy+j][bxx+i] =
imgY_original[pic_pix_y+incr_y*(j+byy)+off_y/*lgp*/][pic_pix_x+i] - img->mpr[i+block_x][j+block_y];/*lgp*///b
}
}
}
mcost += find_sad_8x8(input->hadamard,8,8,0,0,curr_blk);
return mcost;
}
/*
*************************************************************************
* Function:Get cost for skip mode for an macroblock
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int GetSkipCostMB (double lambda)
{
int block_y, block_x, pic_pix_y, pic_pix_x, i, j, k;
int diff[16];
int cost = 0;
int pix_x = img->pix_x;
int pix_y = img->pix_y;
byte** imgY_org_pic = imgY_org;
//int incr_y=1,off_y=0;/*lgp*///b
for (block_y=0; block_y<16; block_y+=4)
{
pic_pix_y = pix_y + block_y;
/*lgp*///b
for (block_x=0; block_x<16; block_x+=4)
{
pic_pix_x = pix_x + block_x;
//===== prediction of 4x4 block =====
LumaPrediction4x4 (block_x, block_y, 0, 0, 0, 0);
//===== get displaced frame difference ======
for (k=j=0; j<4; j++)
for (i=0; i<4; i++, k++)
{
diff[k] = imgY_org_pic[pic_pix_y+j][pic_pix_x+i] - img->mpr[i+block_x][j+block_y];/*lgp*///b
}
cost += SATD (diff, input->hadamard);
}
}
return cost;
}
/*
*************************************************************************
* Function:Find motion vector for the Skip mode
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void FindSkipModeMotionVector ()
{
int bx, by;
int mb_nr = img->current_mb_nr;
int mb_width = img->width/16;
//int mb_available_up = (img->mb_y == 0) ? 0 : 1;
int mb_available_up = (img->mb_y == 0 ) ? 0 : (img->mb_data[mb_nr].slice_nr == img->mb_data[mb_nr-mb_width ].slice_nr); //jlzheng 6.23
//int mb_available_left = (img->mb_x == 0) ? 0 : 1;
int mb_available_left = (img->mb_x == 0 ) ? 0 : (img->mb_data[mb_nr].slice_nr == img->mb_data[mb_nr-1 ].slice_nr);
int zeroMotionAbove = !mb_available_up ? 1 : refFrArr[(img->block_y>>1)-1][(img->block_x>>1)] == 0 &amt;&amt; tmp_mv[0][(img->block_y>>1)-1][4+(img->block_x>>1)] == 0 &amt;&amt; tmp_mv[1][(img->block_y>>1)-1][4+(img->block_x>>1)] == 0 ? 1 : 0;
int zeroMotionLeft = !mb_available_left? 1 : refFrArr[(img->block_y>>1)][(img->block_x>>1)-1] == 0 &amt;&amt; tmp_mv[0][(img->block_y>>1) ][4+(img->block_x>>1)-1] == 0 &amt;&amt; tmp_mv[1][(img->block_y>>1) ][4+(img->block_x>>1)-1] == 0 ? 1 : 0;
int mb_x = img->mb_x;
int mb_y = img->mb_y;
int block_x = img->block_x;
int block_y = img->block_y;
int **refar = refFrArr;
int ***tmpmv = tmp_mv;
int *****all_mv = img->all_mv;
//int *****mv = img->mv;
int *mv = img->mv[0][0][0][0];
if (zeroMotionAbove || zeroMotionLeft)
{
for (by = 0;by < 2;by++)
for (bx = 0;bx < 2;bx++)
{
all_mv [bx][by][0][0][0] = 0;
all_mv [bx][by][0][0][1] = 0;
}
}
else
{
// for (by = 0;by < 2;by++)
// for (bx = 0;bx < 2;bx++)
// {
// all_mv [bx][by][0][0][0] = mv[0][0][0][1][0];
// all_mv [bx][by][0][0][1] = mv[0][0][0][1][1];
// }
//for skip and 16x16 use the same block size if 16x16 is disable
//the skip should not be disable
//cjw 20060327 qhg when 16x16 is disable, skip and 16x16 should use the different
//motion vectorpredictor
SetMotionVectorPredictor(mv,refar,tmpmv,0,0,0,16,16, 0, 0);
for (by = 0;by < 2;by++)
for (bx = 0;bx < 2;bx++)
{
all_mv [bx][by][0][0][0] = mv[0];
all_mv [bx][by][0][0][1] = mv[1];
}
}
}
/*
*************************************************************************
* Function:Get cost for direct mode for an 8x8 block
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int Get_Direct_Cost8x8 (int block, double lambda)
{
int block_y, block_x, pic_pix_y, pic_pix_x, i, j, k;
int diff[16];
int cost = 0;
int mb_y = (block/2)<<3;
int mb_x = (block>2)<<3;
int curr_blk[MB_BLOCK_SIZE][MB_BLOCK_SIZE]; // pred.error buffer for 8x8
int bxx, byy; // indexing curr_blk
byte **imgY_original = imgY_org;
int pix_y = img->pix_y;
/*lgp*///b
for (byy=0, block_y=mb_y; block_y<mb_y+8; byy+=4, block_y+=4)
{
pic_pix_y = pix_y + block_y;
for (bxx=0, block_x=mb_x; block_x<mb_x+8; bxx+=4, block_x+=4)
{
pic_pix_x = img->pix_x + block_x;
//===== prediction of 4x4 block =====
LumaPrediction4x4 (block_x, block_y, 0, 0, max(0,refFrArr[pic_pix_y>>2][pic_pix_x>>2]), 0);
//===== get displaced frame difference ======
for (k=j=0; j<4; j++)
for (i=0; i<4; i++, k++)
{
diff[k] = curr_blk[byy+j][bxx+i] =
imgY_original[pic_pix_y+j][pic_pix_x+i] - img->mpr[i+block_x][j+block_y];
}
}
}
cost += find_sad_8x8(input->hadamard,8,8,0,0,curr_blk);
return cost;
}
/*
*************************************************************************
* Function:Get cost for direct mode for an macroblock
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int Get_Direct_CostMB (double lambda)
{
int i;
int cost = 0;
/*lgp*///b
for (i=0; i<4; i++)
{
cost += Get_Direct_Cost8x8 (i, lambda);
}
return cost;
}
/*
*************************************************************************
* Function:Motion search for a partition
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void PartitionMotionSearch (int blocktype,
int block8x8,
double lambda)
{
static int bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,1,0,0}, {0,1,0,1}};
static int by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,1,0,0}, {0,0,0,0}, {0,0,1,1}};
int **ref_array, ***mv_array, *****all_mv;
int ref, refinx, refframe, v, h, mcost, search_range, i, j;
int pic_block_x, pic_block_y;
int bframe = (img->type==B_IMG);
int max_ref = bframe? img->nb_references-1 : img->nb_references;
int parttype = (blocktype<4?blocktype:4);
int step_h0 = (input->blc_size[ parttype][0]>>3);
int step_v0 = (input->blc_size[ parttype][1]>>3);
int step_h = (input->blc_size[blocktype][0]>>3);
int step_v = (input->blc_size[blocktype][1]>>3);
int block_x = img->block_x;
int block_y = img->block_y;
int min_ref = (bframe?-1:0);/*lgp13*/
if(img->type==B_IMG) max_ref =1; /*lgp*/
if (max_ref > img->buf_cycle)
max_ref = img->buf_cycle;
if (mref[0] == mref_fld[0])
{
if (img->type == B_IMG)
{
max_ref = 2;
min_ref = -2;
}
}
//===== LOOP OVER REFERENCE FRAMES =====
for (ref=min_ref/*lgp13*/; ref<max_ref; ref++)
{
refinx = ref+1;
refframe = (ref<0?0:ref);
if (mref[0] == mref_fld[0])
{
if (img->type == B_IMG)
{
refinx = ref+2;
refframe = (ref<0?ref+2:ref); // Yulj 2004.07.15
}
}
//----- set search range ---
search_range = input->search_range;
//----- set arrays -----
ref_array = ((img->type!=B_IMG) ? refFrArr : ref<0 ? bw_refFrArr : fw_refFrArr);
mv_array = ((img->type!=B_IMG) ? tmp_mv : ref<0 ? tmp_bwMV : tmp_fwMV);
all_mv = (ref<0 ? img->all_bmv : img->all_mv);
//----- init motion cost -----
motion_cost[blocktype][refinx][block8x8] = 0;
//===== LOOP OVER BLOCKS =====
for (v=by0[parttype][block8x8]; v<by0[parttype][block8x8]+step_v0; v+=step_v)
{
pic_block_y = (block_y>>1) + v;
for (h=bx0[parttype][block8x8]; h<bx0[parttype][block8x8]+step_h0; h+=step_h)
{
pic_block_x = (block_x>>1) + h;
//--- motion search for block ---
#ifdef FastME
mcost = FME_BlockMotionSearch (ref, 8*pic_block_x, 8*pic_block_y, blocktype, search_range, lambda);//should modify the constant?
#else
mcost = BlockMotionSearch (ref, 8*pic_block_x, 8*pic_block_y, blocktype, search_range, lambda);
#endif
motion_cost[blocktype][refinx][block8x8] += mcost;
//--- set motion vectors and reference frame (for motion vector prediction) ---
for (j=0; j<step_v; j++)
for (i=0; i<step_h; i++)
{
mv_array[0][pic_block_y+j][pic_block_x+i+4] = all_mv[h][v][refframe][blocktype][0];
mv_array[1][pic_block_y+j][pic_block_x+i+4] = all_mv[h][v][refframe][blocktype][1];
ref_array [pic_block_y+j][pic_block_x+i ] = refframe;
}
}
}
}
}
/*
*************************************************************************
* Function:Motion search for a partition
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void
PartitionMotionSearch_bid (int blocktype,
int block8x8,
double lambda)
{
static int bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,1,0,0}, {0,1,0,1}};
static int by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,1,0,0}, {0,0,0,0}, {0,0,1,1}};
int **ref_array, ***mv_array, *****all_mv;
int ref, refinx, refframe, v, h, mcost, search_range, i, j;
int pic_block_x, pic_block_y;
int bframe = (img->type==B_IMG);
int max_ref = bframe? img->nb_references-1 : img->nb_references;
int parttype = (blocktype<4?blocktype:4);
int step_h0 = (input->blc_size[ parttype][0]>>3);
int step_v0 = (input->blc_size[ parttype][1]>>3);
int step_h = (input->blc_size[blocktype][0]>>3);
int step_v = (input->blc_size[blocktype][1]>>3);
int block_y = img->block_y;
int min_ref;
if(img->type==B_IMG) max_ref = 1;
if (max_ref > img->buf_cycle) max_ref = img->buf_cycle;
if (mref[0] == mref_fld[0])
{
if (img->type == B_IMG)
{
max_ref = 2;
min_ref = -2;
}
}
//===== LOOP OVER REFERENCE FRAMES =====
for (ref=0; ref<max_ref; ref++)
{
refinx = ref+1;
refframe = (ref<0?0:ref);
if (mref[0] == mref_fld[0])
{
if (img->type == B_IMG)
{
refinx = ref+2;
refframe = (ref<0?ref+2:ref);
}
}
search_range = input->search_range;
//----- set arrays -----
ref_array = ((img->type!=B_IMG) ? refFrArr : ref<0 ? bw_refFrArr : fw_refFrArr);
mv_array = ((img->type!=B_IMG) ? tmp_mv : ref<0 ? tmp_bwMV : tmp_fwMV);
//sw 10.1
//all_mv = (ref<0 ? img->all_bmv : img->all_mv);
all_mv = (ref<0 ? img->all_bmv : img->all_omv);
//----- init motion cost -----
motion_cost_bid[blocktype][refinx][block8x8] = 0;
//===== LOOP OVER BLOCKS =====
for (v=by0[parttype][block8x8]; v<by0[parttype][block8x8]+step_v0; v+=step_v)
{
pic_block_y = (block_y>>1) + v;
for (h=bx0[parttype][block8x8]; h<bx0[parttype][block8x8]+step_h0; h+=step_h)
{
pic_block_x = (img->block_x>>1) + h;
//--- motion search for block ---
#ifdef FastME
mcost = FME_BlockMotionSearch_bid (ref, 8*pic_block_x, 8*pic_block_y, blocktype, search_range, lambda);//modify?
#else
mcost = BlockMotionSearch_bid (ref, 8*pic_block_x, 8*pic_block_y, blocktype, search_range, lambda);
#endif
motion_cost_bid[blocktype][refinx][block8x8] += mcost;
//--- set motion vectors and reference frame (for motion vector prediction) ---
for (j=0; j<step_v; j++)
for (i=0; i<step_h; i++)
{
mv_array[0][pic_block_y+j][pic_block_x+i+4] = all_mv[h][v][refframe][blocktype][0];
mv_array[1][pic_block_y+j][pic_block_x+i+4] = all_mv[h][v][refframe][blocktype][1];
ref_array [pic_block_y+j][pic_block_x+i ] = refframe;
}
}
}
}
}
extern int* last_P_no;
/*********************************************
***** *****
***** Calculate Direct Motion Vectors *****
***** *****
*********************************************/
/*
*************************************************************************
* Function:
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void Get_IP_direct()
{
int block_x, block_y, pic_block_x, pic_block_y;
int refframe, bw_ref, refP_tr, TRb, TRp, TRd, TRp1;
int frame_no_next_P, frame_no_B, delta_P;
int pix_y = img->pix_y;
int **refarr = refFrArr;
int ***tmpmvs = tmp_mv;
int *****all_mvs = img->all_mv;
int *****all_bmvs = img->all_bmv;
int prev_mb_is_field = 0;
int mv_scale, scale_refframe;
int **fwrefarr = fw_refFrArr;
int **bwrefarr = bw_refFrArr;
int ***tmpmvfw = tmp_fwMV;
int ***tmpmvbw = tmp_bwMV;
pic_block_x = img->block_x;
pic_block_y = img->block_y;
for (block_y=0; block_y<2; block_y++)
{
pic_block_y = (pix_y>>3) + block_y;
for (block_x=0; block_x<2; block_x++)
{
pic_block_x = (img->pix_x>>3) + block_x;
if((refframe=refarr[pic_block_y][pic_block_x]) == -1)
{
all_mvs [block_x][block_y][0][0][0] = 0;
all_mvs[block_x][block_y][0][0][1] = 0;
all_bmvs[block_x][block_y][0][0][0] = 0;
all_bmvs[block_x][block_y][0][0][1] = 0;
SetMotionVectorPredictor(all_mvs [block_x][block_y][0][0],fwrefarr,tmpmvfw,0,0,0,16,16, 0, 1);//Lou 1016
SetMotionVectorPredictor(all_bmvs [block_x][block_y][img->picture_structure?0:1][0],bwrefarr,tmpmvbw,img->picture_structure?0:1,0,0,16,16, -1, 1);//Lou 1016
}
else
{
refP_tr = nextP_tr - ((refframe+1)*img->p_interval);
frame_no_next_P = 2*img->imgtr_next_P_frm;
frame_no_B = 2*img->tr;
delta_P = 2*(img->imgtr_next_P_frm - img->imgtr_last_P_frm);
if(!img->picture_structure)
{
if (img->current_mb_nr_fld < img->total_number_mb) //top field
scale_refframe = refframe == 0 ? 0 : 1;
else
scale_refframe = refframe == 1 ? 1 : 2;
}
else
scale_refframe = 0;
if(!img->picture_structure)
{
if (img->current_mb_nr_fld < img->total_number_mb) //top field
{
TRp = delta_P*(refframe/2+1)-(refframe+1)>2; //the lates backward reference
TRp1 = delta_P*(scale_refframe/2+1)-(scale_refframe+1)>2; //the lates backward reference
bw_ref = 1;
}
else
{
TRp = 1 + delta_P*((refframe+1)/2)-refframe>2;
TRp1 = 1 + delta_P*((scale_refframe+1)/2)-scale_refframe>2;
bw_ref = 0;
}
}
else
{
TRp = (refframe+1)*delta_P;
TRp1 = (scale_refframe+1)*delta_P;
}
TRd = frame_no_next_P - frame_no_B;
TRb = TRp1 - TRd;
mv_scale = (TRb * 256) / TRp; //! Note that this could be precomputed at the frame/slice level.
refframe = 0;
if(!img->picture_structure)
{
if (img->current_mb_nr_fld >= img->total_number_mb) //top field
scale_refframe --;
refframe = scale_refframe;
}else
{
refframe = 0;
bw_ref = 0;
}
if(tmpmvs[0][pic_block_y][pic_block_x+4] < 0)
{
all_mvs [block_x][block_y][refframe][0][0] = -(((16384/TRp)*(1-TRb*tmpmvs[0][pic_block_y][pic_block_x+4])-1)>>14);
all_bmvs [block_x][block_y][bw_ref][0][0] = ((16384/TRp)*(1-TRd*tmpmvs[0][pic_block_y][pic_block_x+4])-1)>>14;
}
else
{
all_mvs [block_x][block_y][refframe][0][0] = ((16384/TRp)*(1+TRb*tmpmvs[0][pic_block_y][pic_block_x+4])-1)>>14;
all_bmvs [block_x][block_y][bw_ref][0][0] = -(((16384/TRp)*(1+TRd*tmpmvs[0][pic_block_y][pic_block_x+4])-1)>>14);
}
if(tmpmvs[1][pic_block_y][pic_block_x+4] < 0)
{
all_mvs [block_x][block_y][refframe][0][1] = -(((16384/TRp)*(1-TRb*tmpmvs[1][pic_block_y][pic_block_x+4])-1)>>14);
all_bmvs [block_x][block_y][bw_ref][0][1] = ((16384/TRp)*(1-TRd*tmpmvs[1][pic_block_y][pic_block_x+4])-1)>>14;
}
else
{
all_mvs [block_x][block_y][refframe][0][1] = ((16384/TRp)*(1+TRb*tmpmvs[1][pic_block_y][pic_block_x+4])-1)>>14;
all_bmvs [block_x][block_y][bw_ref][0][1] = -(((16384/TRp)*(1+TRd*tmpmvs[1][pic_block_y][pic_block_x+4])-1)>>14);
}
}
}
}
}
/*
*************************************************************************
* Function:control the sign of a with b
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
int sign(int a,int b)
{
int x;
x=absm(a);
if (b >= 0)
return x;
else
return -x;
}