2 /**************************************************************************
4 * This code is developed by Adam Li. This software is an *
5 * implementation of a part of one or more MPEG-4 Video tools as *
6 * specified in ISO/IEC 14496-2 standard. Those intending to use this *
7 * software module in hardware or software products are advised that its *
8 * use may infringe existing patents or copyrights, and any such use *
9 * would be at such party's own risk. The original developer of this *
10 * software module and his/her company, and subsequent editors and their *
11 * companies (including Project Mayo), will have no liability for use of *
12 * this software or modifications or derivatives thereof. *
14 * Project Mayo gives users of the Codec a license to this software *
15 * module or modifications thereof for use in hardware or software *
16 * products claiming conformance to the MPEG-4 Video Standard as *
17 * described in the Open DivX license. *
19 * The complete Open DivX license can be found at *
20 * http://www.projectmayo.com/opendivx/license.php . *
22 **************************************************************************/
24 /**************************************************************************
28 * Copyright (C) 2001 Project Mayo
32 * DivX Advance Research Center <darc@projectmayo.com>
34 **************************************************************************/
36 /* This file contains some functions to do motion estimation and */
37 /* for one MacroBlock in one pass. */
38 /* Some codes of this project come from MoMuSys MPEG-4 implementation. */
39 /* Please see seperate acknowledgement file for a list of contributors. */
43 /* Obtaining if two floating point values are equal*/
44 #define ABSDOUBLE(x) (((x) > 0.0001) ? (x) : (((x) < -0.0001) ? -(x): 0.0 ))
45 #define ARE_EQUAL(x,y) ( (ABSDOUBLE((Float)(x)-(y))>0.1)?(0):(1) )
47 /* auxiliar define for indexing in MBMotionEstimation */
48 #define INDEX_BIG(x,y) ((x)+(y)*(vop_width))
49 #define INDEX_NOR(x,y) ((x)+(y)*(MB_SIZE))
51 /* ------------------------------------------------------------------------- */
53 /***********************************************************CommentBegin******
55 * -- RangeInSearchArea -- computes the range of the search area
58 * computes the range of the search area for the predicted MV's
59 * INSIDE the overlapped zone between reference and current vops
61 ***********************************************************CommentEnd********/
65 Int i
, /* <-- horizontal MBcoordinate in pixels */
66 Int j
, /* <-- vertical MB coordinate in pixels */
67 Int block
, /* <-- block position (0 16x16; 1-2-3-4 8x8) */
68 Int prev_x
, /* <-- absolute horizontal position of the previous vop*/
69 Int prev_y
, /* <-- absolute vertical position of the previous vop */
70 Int vop_width
, /* <-- horizontal vop dimension */
71 Int vop_height
, /* <-- vertical vop dimension */
72 Int br_x
, /* <-- absolute horizontal position of the current vop */
73 Int br_y
, /* <-- absolute vertical position of the current vop */
74 Int edge
, /* <-- edge arround the reference vop */
75 Int f_code
, /* <- MV search range 1/2 (or 1/4) pel: (0=16,) 1=32,2=64,...,7=2048 */
76 Float
*mv_x_min
, /* <-- min horizontal range */
77 Float
*mv_x_max
, /* <-- max horizontal range */
78 Float
*mv_y_min
, /* <-- min vertical range */
79 Float
*mv_y_max
, /* <-- max vertical range */
80 Int
*out
/* --> the search area does not exist (the reference */ /* and current BB does not overlap) */
99 case 0: /* 8x8 or 16x16 block search */
100 block_x
=0; /*****************************/
101 block_y
=0; /** 1 2 ******** 0 *********/
102 mb_b_size
=MB_SIZE
; /** 3 4 ******** *********/
103 break; /*****************************/
129 dim_curr_x_min
=(Int
)(br_x
+i
*MB_SIZE
+*mv_x_min
+block_x
);
130 dim_curr_y_min
=(Int
)(br_y
+j
*MB_SIZE
+*mv_y_min
+block_y
);
131 dim_prev_x_min
=prev_x
/*-edge*/;
132 dim_prev_y_min
=prev_y
/*-edge*/;
135 /*the MB right-pixels inside */
136 dim_curr_x_max
=(Int
)(br_x
+i
*MB_SIZE
+*mv_x_max
+mb_b_size
+block_x
);
137 /*the MB bottom-pixels inside */
138 dim_curr_y_max
=(Int
)(br_y
+j
*MB_SIZE
+*mv_y_max
+mb_b_size
+block_y
);
139 dim_prev_x_max
=prev_x
+vop_width
/*+edge*/;
140 dim_prev_y_max
=prev_y
+vop_height
/*+edge*/;
144 if (dim_curr_x_min
> dim_prev_x_max
)
148 else if(dim_curr_x_min
< dim_prev_x_min
)
150 *mv_x_min
= *mv_x_min
+ ( dim_prev_x_min
- dim_curr_x_min
) ;
155 if (dim_curr_y_min
> dim_prev_y_max
)
159 else if(dim_curr_y_min
< dim_prev_y_min
)
161 *mv_y_min
= *mv_y_min
+ ( dim_prev_y_min
- dim_curr_y_min
) ;
168 if(dim_curr_x_max
< dim_prev_x_min
)
172 if ((!(*out
))&&(dim_curr_x_max
> dim_prev_x_max
))
174 *mv_x_max
= *mv_x_max
- ( dim_curr_x_max
- dim_prev_x_max
) ;
180 if(dim_curr_y_max
< dim_prev_y_min
)
182 *out
=1; /* already set */
184 if ((!(*out
))&&(dim_curr_y_max
> dim_prev_y_max
))
186 *mv_y_max
= *mv_y_max
- ( dim_curr_y_max
- dim_prev_y_max
) ;
190 if(*mv_x_min
>*mv_x_max
)
195 if ( (!(*out
)) && (*mv_y_min
>*mv_y_max
))
204 /***********************************************************CommentBegin******
206 * -- Obtain_Range -- computes the range of the search area
209 * computes the range of the search area for the predicted MV's
210 * (it can be outside the overlapped zone between the reference
214 * 1 on success, 0 on error
216 ***********************************************************CommentEnd********/
220 Int f_code
, /* <-- MV search range 1/2 (or 1/4 pel): (0=16,) 1=32,2=64,...,7=2048 */
221 Int sr
, /* <-- Serach range (radius) */
222 Int type
, /* <-- MBM_INTER16==16x16 search; MBM_INTER8==8x8 search */
223 Float pmv_x
, /* <-- predicted horizontal motion vector */
224 Float pmv_y
, /* <-- predicted horizontal motion vector */
225 Float
*mv_x_min
, /* --> min horizontal range */
226 Float
*mv_x_max
, /* --> max horizontal range */
227 Float
*mv_y_min
, /* --> min vertical range */
228 Float
*mv_y_max
, /* --> max vertical range */
229 Int quarter_pel
/* <-- quarter pel flag (to allow f_code==0 without sprite) */
234 Float aux_x_min
, aux_y_min
,
235 aux_x_max
, aux_y_max
;
241 if ((f_code
==0) && (!quarter_pel
)) /* for Low Latency Sprite */
252 *mv_x_min
=-range
; *mv_x_max
= range
- 0.5f
;
254 *mv_y_min
=-range
; *mv_y_max
= range
- 0.5f
;
257 if (type
==MBM_INTER8
)
259 aux_x_min
=pmv_x
- DEFAULT_8_WIN
;
260 aux_y_min
=pmv_y
- DEFAULT_8_WIN
;
261 aux_x_max
=pmv_x
+ DEFAULT_8_WIN
;
262 aux_y_max
=pmv_y
+ DEFAULT_8_WIN
;
264 if(*mv_x_min
< aux_x_min
)
265 *mv_x_min
= aux_x_min
;
266 if(*mv_y_min
< aux_y_min
)
267 *mv_y_min
= aux_y_min
;
268 if(*mv_x_max
> aux_x_max
)
269 *mv_x_max
= aux_x_max
;
270 if(*mv_y_max
> aux_y_max
)
271 *mv_y_max
= aux_y_max
;
281 /***********************************************************CommentBegin******
283 * -- MBMotionEstimation -- Computes INTEGER PRECISION MV's for a MB
286 * Computes INTEGER PRECISION MV's for a MB. Also returns
287 * prediction errors. Requires the whole MVs data images to
288 * obtain prediction for the current MV, which determines search
291 ***********************************************************CommentEnd********/
295 SInt
*curr
, /* <-- Current vop pointer */
296 SInt
*prev
, /* <-- extended reference picture */
297 Int br_x
, /* <-- horizontal bounding rectangle coordinate */
298 Int br_y
, /* <-- vertical bounding rectangle coordinate */
299 Int br_width
, /* <-- bounding rectangule width */
300 Int i
, /* <-- horizontal MBcoordinate in pixels */
301 Int j
, /* <-- vertical MB coordinate in pixels */
302 Int prev_x
, /* <-- absolute horiz. position of previous vop */
303 Int prev_y
, /* <-- absolute verti. position of previous vop */
304 Int vop_width
, /* <-- horizontal vop dimension */
305 Int vop_height
, /* <-- vertical vop dimension */
306 Int enable_8x8_mv
, /* <-- 8x8 MV (=1) or only 16x16 MV (=0) */
307 Int edge
, /* <-- edge */
308 Int f_code
, /* <-- MV search range 1/2 (or 1/4) pel: (0=16,) 1=32,2=64,...,7=2048*/
309 Int sr
, /* <-- search range (corresponds to f_code) UB 990215*/
310 Float hint_mv_w
, /* <-- hint seed for horizontal MV */
311 Float hint_mv_h
, /* <-- hint seed for vertical MV */
312 Float
*mv16_w
, /* --> predicted horizontal 16x16 MV(if approp.) */
313 Float
*mv16_h
, /* --> predicted vertical 16x16 MV (if approp.) */
314 Float
*mv8_w
, /* --> predicted horizontal 8x8 MV (if approp.) */
315 Float
*mv8_h
, /* --> predicted vertical 8x8 MV (if approp.) */
316 Int
*min_error
, /* --> Minimum prediction error */
321 Int sad
, sad_min
=MV_MAX_ERROR
;
325 SInt act_block
[MB_SIZE
*MB_SIZE
];
327 Float mv_x_min
, mv_x_max
,
329 Int int_mv_x_min
=0, int_mv_x_max
=0,
330 int_mv_y_min
=0, int_mv_y_max
=0;
333 Int mvm_width
= br_width
/MB_SIZE
;
335 Int x_curr
= i
*MB_SIZE
,
343 Int min_error16
, min_error8
= 0;
344 // SInt *curr = (SInt *)GetImageData(GetVopY(curr_vop));
345 #ifndef _FULL_SEARCH_ /* PIH (NTU) Fast ME 08/08/99 */
358 SInt d_type
=1,stop_flag
=0,pt_nmbr
=0,check_pts
,total_check_pts
=8,mot_dirn
=0;
359 Int d_centre_x
=0,d_centre_y
=0,check_pt_x
,check_pt_y
;
363 { {0,1,0}, {1,0,0}, {0,-1,0}, {-1,0,0} }
367 { {0,2,6}, {1,1,0}, {2,0,0}, {1,-1,2},
368 {0,-2,2}, {-1,-1,4}, {-2,0,4}, {-1,1,6} }
373 d_centre_x
= (int)hint_mv_w
;
374 d_centre_y
= (int)hint_mv_h
;
376 rel_ori_x
=br_x
-prev_x
;
377 rel_ori_y
=br_y
-prev_y
;
381 LoadArea(curr
, x_curr
,y_curr
,MB_SIZE
,MB_SIZE
,br_width
, act_block
);
383 /* Compute 16x16 integer MVs */
387 Obtain_Range (f_code
, sr
, MBM_INTER16
, /* UB 990215 added search range */
388 0.0, 0.0, &mv_x_min
, &mv_x_max
,
389 /*UB 990215 added quarter pel support */
390 &mv_y_min
, &mv_y_max
, 0/*GetVopQuarterPel(curr_vop)*/);
392 RangeInSearchArea (i
,j
,0, prev_x
, prev_y
, vop_width
, vop_height
,
393 br_x
, br_y
, edge
,f_code
, &mv_x_min
, &mv_x_max
,
394 /*UB 990215 added quarter pel support */
395 &mv_y_min
, &mv_y_max
,&out
);
401 int_mv_x_min
=(int)ceil((double)mv_x_min
);
402 int_mv_y_min
=(int)ceil((double)mv_y_min
);
403 int_mv_x_max
=(int)floor((double)mv_x_max
);
404 int_mv_y_max
=(int)floor((double)mv_y_max
);
405 flags
[0]=ARE_EQUAL(int_mv_x_min
,mv_x_min
);
406 flags
[1]=ARE_EQUAL(int_mv_x_max
,mv_x_max
);
407 flags
[2]=ARE_EQUAL(int_mv_y_min
,mv_y_min
);
408 flags
[3]=ARE_EQUAL(int_mv_y_max
,mv_y_max
);
410 sad_min
=MV_MAX_ERROR
;
411 mv_x
= mv_y
= 2000; /* A very large MV */
413 #ifdef _FULL_SEARCH_ /* PIH (NTU) 08/08/99 */
414 for (y
=int_mv_y_min
; y
<=int_mv_y_max
; y
++)
415 for (x
=int_mv_x_min
; x
<=int_mv_x_max
; x
++)
418 sad
=SAD_Macroblock(prev
+INDEX_BIG(x_curr
+rel_ori_x
,
419 y_curr
+rel_ori_y
), act_block
,
420 (vop_width
/*+2*edge*/), MV_MAX_ERROR
)
423 sad
=SAD_Macroblock(prev
+INDEX_BIG(x_curr
+x
+rel_ori_x
,
424 y_curr
+y
+rel_ori_y
), act_block
,
425 (vop_width
/*+2*edge*/), sad_min
);
433 else if (sad
==sad_min
)
434 if((ABS(x
)+ABS(y
)) < (ABS(mv_x
)+ABS(mv_y
)))
441 #else /* PIH (NTU) Fast ME 08/08/99 */
442 sad
= SAD_Macroblock(prev
+INDEX_BIG(x_curr
+rel_ori_x
,
443 y_curr
+rel_ori_y
), act_block
, (vop_width
/*+2*edge*/), MV_MAX_ERROR
)
452 check_pts
=total_check_pts
;
456 check_pt_x
= diamond
[d_type
].point
[pt_nmbr
].x
+ d_centre_x
;
457 check_pt_y
= diamond
[d_type
].point
[pt_nmbr
].y
+ d_centre_y
;
459 /* Restrict the search to the searching window ; Note: This constraint can be removed */
460 if ( check_pt_x
< int_mv_x_min
|| check_pt_x
> int_mv_x_max
|| check_pt_y
< int_mv_y_min
|| check_pt_y
> int_mv_y_max
)
466 sad
=SAD_Macroblock(prev
+INDEX_BIG(x_curr
+check_pt_x
+rel_ori_x
,
467 y_curr
+check_pt_y
+rel_ori_y
), act_block
,
468 (vop_width
/*+2*edge*/), sad_min
);
470 fprintf(stdout
,"+o+ [%2d,%2d] sad16(%3d,%3d)=%4d\n",i
,j
,x
,y
,sad
);
480 else if (sad
==sad_min
)
481 if((ABS(check_pt_x
)+ABS(check_pt_y
)) < (ABS(mv_x
)+ABS(mv_y
)))
490 if((pt_nmbr
)>= 8) pt_nmbr
-=8;
502 if( (mv_x
== d_centre_x
) && (mv_y
== d_centre_y
) )
510 if((mv_x
==d_centre_x
) ||(mv_y
==d_centre_y
))
514 pt_nmbr
=diamond
[d_type
].point
[mot_dirn
].start_nmbr
;
524 flags
[0]=flags
[0] && (mv_x
==int_mv_x_min
);
525 flags
[1]=flags
[1] && (mv_x
==int_mv_x_max
);
526 flags
[2]=flags
[2] && (mv_y
==int_mv_y_min
);
527 flags
[3]=flags
[3] && (mv_y
==int_mv_y_max
);
532 sad_min
=MV_MAX_ERROR
;
537 out
|=((mv_x
==2000)||(mv_y
==2000));
541 sad_min
=MV_MAX_ERROR
;
544 pos16
=2*j
*2*mvm_width
+ 2*i
;
545 mv16_w
[pos16
]= mv_x
; mv16_h
[pos16
]= mv_y
;
546 mv16_w
[pos16
+1]= mv_x
; mv16_h
[pos16
+1]= mv_y
;
548 mv16_w
[pos16
]= mv_x
; mv16_h
[pos16
]= mv_y
;
549 mv16_w
[pos16
+1]= mv_x
; mv16_h
[pos16
+1]= mv_y
;
550 min_error16
= sad_min
;
552 *min_error
= min_error16
;
554 /* Compute 8x8 MVs */
560 for (block
=0;block
<4;block
++)
580 /* VM 2.*: restrict the search range based on the current 16x16 MV
581 * inside a window around it
584 pmv_x
=mv16_w
[pos16
]; pmv_y
=mv16_h
[pos16
];
586 /* UB 990215 added search range */
587 Obtain_Range(f_code
, sr
, MBM_INTER8
,
588 pmv_x
, pmv_y
, &mv_x_min
,
589 /*UB 990215 added quarter pel support */
590 &mv_x_max
, &mv_y_min
, &mv_y_max
, 0 /*GetVopQuarterPel(curr_vop)*/);
592 RangeInSearchArea(i
,j
, block
+1, prev_x
, prev_y
,
593 vop_width
, vop_height
, br_x
, br_y
, edge
,f_code
,
594 /*UB 990215 added quarter pel support */
595 &mv_x_min
, &mv_x_max
, &mv_y_min
,&mv_y_max
,&out
);
599 int_mv_x_min
=(int)ceil((double)mv_x_min
);
600 int_mv_y_min
=(int)ceil((double)mv_y_min
);
601 int_mv_x_max
=(int)floor((double)mv_x_max
);
602 int_mv_y_max
=(int)floor((double)mv_y_max
);
603 flags
[4+block
*4]=ARE_EQUAL(int_mv_x_min
,mv_x_min
);
604 flags
[4+block
*4+1]=ARE_EQUAL(int_mv_x_max
,mv_x_max
);
605 flags
[4+block
*4+2]=ARE_EQUAL(int_mv_y_min
,mv_y_min
);
606 flags
[4+block
*4+3]=ARE_EQUAL(int_mv_y_max
,mv_y_max
);
608 sad_min
=MV_MAX_ERROR
;
609 mv_x
= mv_y
= 2000; /* A very large MV */
611 for (y
=int_mv_y_min
; y
<=int_mv_y_max
; y
++)
612 for (x
=int_mv_x_min
; x
<=int_mv_x_max
; x
++)
615 INDEX_BIG(x_curr
+ x
+ 8*(block
==1||block
==3)+rel_ori_x
,
616 y_curr
+ y
+ 8*(block
==2||block
==3)+rel_ori_y
),
617 act_block
+INDEX_NOR(8*(block
==1||block
==3),
618 8*(block
==2||block
==3)),
619 (vop_width
/*+2*edge*/), sad_min
);
627 else if (sad
==sad_min
)
628 if((ABS(x
)+ABS(y
)) < (ABS(mv_x
)+ABS(mv_y
)))
636 flags
[4+block
*4] = flags
[4+block
*4] && (mv_x
==int_mv_x_min
);
637 flags
[4+block
*4+1] = flags
[4+block
*4+1] && (mv_x
==int_mv_x_max
);
638 flags
[4+block
*4+2] = flags
[4+block
*4+2] && (mv_y
==int_mv_y_min
);
639 flags
[4+block
*4+3] = flags
[4+block
*4+3] && (mv_y
==int_mv_y_max
);
644 sad_min
=MV_MAX_ERROR
;
645 /* punish the OUTER blocks with MV_MAX_ERROR in order to
653 pos8
=2*j
*2*mvm_width
+ 2*i
;
654 min_error8
+= sad_min
;
658 pos8
=2*j
*2*mvm_width
+ 2*i
+1;
659 min_error8
+= sad_min
;
663 pos8
=(2*j
+1)*2*mvm_width
+ 2*i
;
664 min_error8
+= sad_min
;
668 pos8
=(2*j
+1)*2*mvm_width
+ 2*i
+1;
669 min_error8
+= sad_min
;
672 /* Store result: absolute coordinates (note that in restricted mode
678 if (min_error8
< *min_error
)
679 *min_error
= min_error8
;
682 { /* all the four blocks are out */
683 pos8
=2*j
*2*mvm_width
+ 2*i
; mv8_w
[pos8
]=mv8_h
[pos8
]=0.0;
684 pos8
=2*j
*2*mvm_width
+ 2*i
+1; mv8_w
[pos8
]=mv8_h
[pos8
]=0.0;
685 pos8
=(2*j
+1)*2*mvm_width
+ 2*i
; mv8_w
[pos8
]=mv8_h
[pos8
]=0.0;
686 pos8
=(2*j
+1)*2*mvm_width
+ 2*i
+1;mv8_w
[pos8
]=mv8_h
[pos8
]=0.0;
687 min_error8
= MV_MAX_ERROR
;
694 /***********************************************************CommentBegin******
696 * -- FindSubPel -- Computes MV with half-pixel accurary
699 * Computes MV with sub-pixel accurary for a 16x16 or 8x8 block
702 * 1) The preference for the 16x16 null motion vector must be applied
703 * again (now, the SAD is recomputed for the recontructed interpolated
706 ***********************************************************CommentEnd********/
710 Int x
, /* <-- horizontal block coordinate in pixels */
711 Int y
, /* <-- vertical blocl coordinate in pixels */
712 SInt
*prev
, /* <-- interpolated reference vop */
713 SInt
*curr
, /* <-- current block */
714 Int bs_x
, /* <-- hor. block size (8/16) */
715 Int bs_y
, /* <-- vert. block size (8/16) */
716 Int comp
, /* <-- block position in MB (0,1,2,3) */
717 Int rel_x
, /* <-- relative horiz. position between curr & prev vops*/
718 Int rel_y
, /* <-- relative verti. position between curr & prev vops*/
719 Int pels
, /* <-- vop width */
720 Int lines
, /* <-- vop height */
721 Int edge
, /* <-- edge */
722 SInt
*flags
, /* <-- flags */
723 SInt
*curr_comp_mb
, /* <-> motion compensated current mb */
724 Float
*mvx
, /* <-> horizontal motion vector */
725 Float
*mvy
, /* <-> vertical motion vector */
726 Int
*min_error
/* --> prediction error */
729 static PixPoint search
[9] =
731 {0, 0}, {-1, -1}, {0, -1}, {1, -1},
732 {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}
742 lx
, size_x
; /* MW QPEL 07-JUL-1998 */
748 int flag_search
[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
750 Int SubDimension
= 2;
752 lx
= 2*(pels
/*+ 2*edge*/);
754 new_x
= (Int
)((x
+ *mvx
+ rel_x
)*(SubDimension
));
755 new_y
= (Int
)((y
+ *mvy
+ rel_y
)*(SubDimension
));
756 new_x
+= ((comp
&1)<<3)*SubDimension
;
757 new_y
+= ((comp
&2)<<2)*SubDimension
;
761 /** in 1-pixel search we check if we are inside the range; so don't check
765 /* avoids trying outside the reference image */
766 /* we also check with flags if we are inside */
767 /* search range (1==don't make 1/x search by */
775 if (((new_x
/SubDimension
) <= 0/*-edge*/) || *(flags
+flag_pos
)) {
776 flag_search
[1] = flag_search
[4] = flag_search
[6] = 0;
777 } else if (((new_x
/SubDimension
) >= (pels
- bs_x
/*+ edge*/)) || *(flags
+flag_pos
+1)) {
778 flag_search
[3] = flag_search
[5] = flag_search
[8] = 0;
781 if (((new_y
/SubDimension
) <= 0/*-edge*/) || *(flags
+flag_pos
+2)) {
782 flag_search
[1] = flag_search
[2] = flag_search
[3] = 0;
783 } else if (((new_y
/SubDimension
) >= (lines
- bs_y
/*+ edge*/)) || *(flags
+flag_pos
+3)) {
784 flag_search
[6] = flag_search
[7] = flag_search
[8] = 0;
787 AE_min
= MV_MAX_ERROR
;
789 for (i
= 0; i
< 9; i
++)
794 /* estimate on the already interpolated half-pel image */
795 pRef
= prev
+ new_x
+ search
[i
].x
+ (new_y
+ search
[i
].y
) * lx
;
805 AE
+= abs((Int
)*pRef
- (Int
)*pComp
);
814 pRef
+= 2 * lx
- 2 * bs_x
;
815 pComp
+= size_x
- bs_x
;
818 if (i
==0 && bs_y
==16 && *mvx
==0 && *mvy
==0)
827 /* else don't look outside the reference */
830 /* Store optimal values */
832 *mvx
+= ((Float
)search
[min_pos
].x
)/(Float
)(SubDimension
);
833 *mvy
+= ((Float
)search
[min_pos
].y
)/(Float
)(SubDimension
);
835 // generate comp mb data for the minimum point
836 pRef
= prev
+ new_x
+ search
[min_pos
].x
+ (new_y
+ search
[min_pos
].y
) * lx
;
837 pComp
= curr_comp_mb
;
846 pRef
+= 2 * lx
- 2 * bs_x
;