00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "contributors.h"
00019 #include <limits.h>
00020
00021 #include "global.h"
00022 #include "image.h"
00023 #include "memalloc.h"
00024 #include "mb_access.h"
00025 #include "refbuf.h"
00026
00027 #include "me_distortion.h"
00028 #include "me_fullsearch.h"
00029 #include "mv-search.h"
00030
00031
00032 extern short* spiral_search_x;
00033 extern short* spiral_search_y;
00034 extern short* spiral_hpel_search_x;
00035 extern short* spiral_hpel_search_y;
00036
00037
00038
00039
00040
00041
00042
00043
00044 int
00045 FullPelBlockMotionSearch (Macroblock *currMB ,
00046 imgpel* orig_pic,
00047 short ref,
00048 int list,
00049 char ***refPic,
00050 short ****tmp_mv,
00051 int pic_pix_x,
00052 int pic_pix_y,
00053 int blocktype,
00054 MotionVector *pred,
00055 MotionVector *mv,
00056 int search_range,
00057 int min_mcost,
00058 int lambda_factor,
00059 int apply_weights)
00060 {
00061 int pos, cand_x, cand_y, mcost;
00062
00063 StorablePicture *ref_picture = listX[list+currMB->list_offset][ref];
00064
00065 int best_pos = 0;
00066 int max_pos = (2*search_range+1)*(2*search_range+1);
00067 int blocksize_y = params->blc_size[blocktype][1];
00068 int blocksize_x = params->blc_size[blocktype][0];
00069
00070 int pred_x = (pic_pix_x << 2) + pred->mv_x;
00071 int pred_y = (pic_pix_y << 2) + pred->mv_y;
00072 int center_x = pic_pix_x + mv->mv_x;
00073 int center_y = pic_pix_y + mv->mv_y;
00074 int check_for_00 = (blocktype==1 && !params->rdopt && img->type!=B_SLICE && ref==0);
00075 int dist_method = F_PEL + 3 * apply_weights;
00076
00077 ref_pic_sub.luma = ref_picture->p_curr_img_sub;
00078
00079 img_width = ref_picture->size_x;
00080 img_height = ref_picture->size_y;
00081 width_pad = ref_picture->size_x_pad;
00082 height_pad = ref_picture->size_y_pad;
00083
00084 if (ChromaMEEnable)
00085 {
00086 ref_pic_sub.crcb[0] = ref_picture->imgUV_sub[0];
00087 ref_pic_sub.crcb[1] = ref_picture->imgUV_sub[1];
00088 width_pad_cr = ref_picture->size_x_cr_pad;
00089 height_pad_cr = ref_picture->size_y_cr_pad;
00090 }
00091
00092
00093 for (pos=0; pos<max_pos; pos++)
00094 {
00095
00096 cand_x = (center_x + spiral_search_x[pos])<<2;
00097 cand_y = (center_y + spiral_search_y[pos])<<2;
00098
00099
00100 mcost = MV_COST_SMP (lambda_factor, cand_x, cand_y, pred_x, pred_y);
00101 if (check_for_00 && cand_x==pic_pix_x && cand_y==pic_pix_y)
00102 {
00103 mcost -= WEIGHTED_COST (lambda_factor, 16);
00104 }
00105 if (mcost >= min_mcost) continue;
00106
00107
00108 mcost += computeUniPred[dist_method](orig_pic, blocksize_y, blocksize_x,
00109 min_mcost - mcost, cand_x + IMG_PAD_SIZE_TIMES4, cand_y + IMG_PAD_SIZE_TIMES4);
00110
00111
00112 if (mcost < min_mcost)
00113 {
00114 best_pos = pos;
00115 min_mcost = mcost;
00116 }
00117 }
00118
00119
00120
00121 if (best_pos)
00122 {
00123 mv->mv_x += spiral_search_x[best_pos];
00124 mv->mv_y += spiral_search_y[best_pos];
00125 }
00126 return min_mcost;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 int
00136 FullPelBlockMotionBiPred (Macroblock *currMB,
00137 imgpel* orig_pic,
00138 short ref,
00139 int list,
00140 char ***refPic,
00141 short ****tmp_mv,
00142 int pic_pix_x,
00143 int pic_pix_y,
00144 int blocktype,
00145 MotionVector *pred_mv1,
00146 MotionVector *pred_mv2,
00147 MotionVector *mv1,
00148 MotionVector *mv2,
00149 int search_range,
00150 int min_mcost,
00151 int iteration_no,
00152 int lambda_factor,
00153 int apply_weights
00154 )
00155 {
00156 StorablePicture *ref_picture1 = listX[list + currMB->list_offset][ref];
00157 StorablePicture *ref_picture2 = listX[(list ^ 1) + currMB->list_offset][0];
00158 short blocksize_y = params->blc_size[blocktype][1];
00159 short blocksize_x = params->blc_size[blocktype][0];
00160
00161 int pos, mcost;
00162
00163 int best_pos = 0;
00164 int max_pos = (2*search_range+1)*(2*search_range+1);
00165
00166 static MotionVector center1, center2, cand, pred1, pred2;
00167 pred1.mv_x = (pic_pix_x << 2) + pred_mv1->mv_x;
00168 pred1.mv_y = (pic_pix_y << 2) + pred_mv1->mv_y;
00169 pred2.mv_x = (pic_pix_x << 2) + pred_mv2->mv_x;
00170 pred2.mv_y = (pic_pix_y << 2) + pred_mv2->mv_y;
00171 center1.mv_x = pic_pix_x + mv1->mv_x;
00172 center1.mv_y = pic_pix_y + mv1->mv_y;
00173 center2.mv_x = pic_pix_x + mv2->mv_x;
00174 center2.mv_y = pic_pix_y + mv2->mv_y;
00175
00176 ref_pic1_sub.luma = ref_picture1->p_curr_img_sub;
00177 ref_pic2_sub.luma = ref_picture2->p_curr_img_sub;
00178
00179 img_width = ref_picture1->size_x;
00180 img_height = ref_picture1->size_y;
00181 width_pad = ref_picture1->size_x_pad;
00182 height_pad = ref_picture1->size_y_pad;
00183
00184 if (apply_weights)
00185 {
00186 computeBiPred = computeBiPred2[F_PEL];
00187 }
00188 else
00189 {
00190 computeBiPred = computeBiPred1[F_PEL];
00191 }
00192
00193 if ( ChromaMEEnable )
00194 {
00195 ref_pic1_sub.crcb[0] = ref_picture1->imgUV_sub[0];
00196 ref_pic1_sub.crcb[1] = ref_picture1->imgUV_sub[1];
00197 ref_pic2_sub.crcb[0] = ref_picture2->imgUV_sub[0];
00198 ref_pic2_sub.crcb[1] = ref_picture2->imgUV_sub[1];
00199 width_pad_cr = ref_picture1->size_x_cr_pad;
00200 height_pad_cr = ref_picture1->size_y_cr_pad;
00201 }
00202
00203
00204
00205 for (pos=0; pos<max_pos; pos++)
00206 {
00207
00208 cand.mv_x = (center1.mv_x + spiral_search_x[pos])<<2;
00209 cand.mv_y = (center1.mv_y + spiral_search_y[pos])<<2;
00210
00211
00212 mcost = MV_COST_SMP (lambda_factor, cand.mv_x, cand.mv_y, pred1.mv_x, pred1.mv_y);
00213 mcost += MV_COST_SMP (lambda_factor, (center2.mv_x << 2), (center2.mv_y<<2), pred2.mv_x, pred2.mv_y);
00214
00215 if (mcost >= min_mcost) continue;
00216
00217
00218 mcost += computeBiPred(orig_pic,
00219 blocksize_y, blocksize_x, min_mcost - mcost,
00220 cand.mv_x + IMG_PAD_SIZE_TIMES4, cand.mv_y + IMG_PAD_SIZE_TIMES4,
00221 (center2.mv_x << 2) + IMG_PAD_SIZE_TIMES4,
00222 (center2.mv_y << 2) + IMG_PAD_SIZE_TIMES4);
00223
00224
00225 if (mcost < min_mcost)
00226 {
00227 best_pos = pos;
00228 min_mcost = mcost;
00229 }
00230 }
00231
00232
00233 if (best_pos)
00234 {
00235 mv1->mv_x += spiral_search_x[best_pos];
00236 mv1->mv_y += spiral_search_y[best_pos];
00237 }
00238 return min_mcost;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 int
00248 SubPelBlockMotionSearch (imgpel* orig_pic,
00249 short ref,
00250 int list,
00251 int list_offset,
00252 int pic_pix_x,
00253 int pic_pix_y,
00254 int blocktype,
00255 MotionVector *pred,
00256 MotionVector *mv,
00257 int search_pos2,
00258 int search_pos4,
00259 int min_mcost,
00260 int* lambda,
00261 int apply_weights
00262 )
00263 {
00264 int pos, best_pos, mcost;
00265
00266 int cand_mv_x, cand_mv_y;
00267
00268 int check_position0 = (!params->rdopt && img->type!=B_SLICE && ref==0 && blocktype==1 && mv->mv_x == 0 && mv->mv_y ==0);
00269 int blocksize_x = params->blc_size[blocktype][0];
00270 int blocksize_y = params->blc_size[blocktype][1];
00271 int pic4_pix_x = ((pic_pix_x + IMG_PAD_SIZE)<< 2);
00272 int pic4_pix_y = ((pic_pix_y + IMG_PAD_SIZE)<< 2);
00273 int max_pos2 = ( !start_me_refinement_hp ? imax(1,search_pos2) : search_pos2);
00274 int cmv_x, cmv_y;
00275 int dist_method = H_PEL + 3 * apply_weights;
00276 StorablePicture *ref_picture = listX[list+list_offset][ref];
00277
00278 int lambda_factor = lambda[H_PEL];
00279
00280 ref_pic_sub.luma = ref_picture->p_curr_img_sub;
00281 width_pad = ref_picture->size_x_pad;
00282 height_pad = ref_picture->size_y_pad;
00283
00284 if (ChromaMEEnable)
00285 {
00286 ref_pic_sub.crcb[0] = ref_picture->imgUV_sub[0];
00287 ref_pic_sub.crcb[1] = ref_picture->imgUV_sub[1];
00288 width_pad_cr = ref_picture->size_x_cr_pad;
00289 height_pad_cr = ref_picture->size_y_cr_pad;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 for (best_pos = 0, pos = start_me_refinement_hp; pos < max_pos2; pos++)
00300 {
00301 cand_mv_x = mv->mv_x + (spiral_hpel_search_x[pos]);
00302 cand_mv_y = mv->mv_y + (spiral_hpel_search_y[pos]);
00303
00304
00305 mcost = MV_COST_SMP (lambda_factor, cand_mv_x, cand_mv_y, pred->mv_x, pred->mv_y);
00306
00307
00308 if (mcost >= min_mcost) continue;
00309
00310 cmv_x = cand_mv_x + pic4_pix_x;
00311 cmv_y = cand_mv_y + pic4_pix_y;
00312
00313 mcost += computeUniPred[dist_method]( orig_pic, blocksize_y, blocksize_x, min_mcost - mcost, cmv_x, cmv_y);
00314
00315 if (pos==0 && check_position0)
00316 {
00317 mcost -= WEIGHTED_COST (lambda_factor, 16);
00318 }
00319
00320 if (mcost < min_mcost)
00321 {
00322 min_mcost = mcost;
00323 best_pos = pos;
00324 }
00325 }
00326 if (best_pos)
00327 {
00328 mv->mv_x += (spiral_hpel_search_x [best_pos]);
00329 mv->mv_y += (spiral_hpel_search_y [best_pos]);
00330 }
00331
00332 if ( !start_me_refinement_qp )
00333 min_mcost = INT_MAX;
00334
00335
00336
00337
00338
00339
00340
00341 dist_method = Q_PEL + 3 * apply_weights;
00342 lambda_factor = lambda[Q_PEL];
00343
00344
00345 for (best_pos = 0, pos = start_me_refinement_qp; pos < search_pos4; pos++)
00346 {
00347 cand_mv_x = mv->mv_x + spiral_search_x[pos];
00348 cand_mv_y = mv->mv_y + spiral_search_y[pos];
00349
00350
00351 mcost = MV_COST_SMP (lambda_factor, cand_mv_x, cand_mv_y, pred->mv_x, pred->mv_y);
00352
00353 if (mcost >= min_mcost) continue;
00354
00355 cmv_x = cand_mv_x + pic4_pix_x;
00356 cmv_y = cand_mv_y + pic4_pix_y;
00357
00358 mcost += computeUniPred[dist_method]( orig_pic, blocksize_y, blocksize_x, min_mcost - mcost, cmv_x, cmv_y);
00359
00360 if (mcost < min_mcost)
00361 {
00362 min_mcost = mcost;
00363 best_pos = pos;
00364 }
00365 }
00366 if (best_pos)
00367 {
00368 mv->mv_x += spiral_search_x [best_pos];
00369 mv->mv_y += spiral_search_y [best_pos];
00370 }
00371
00372
00373 return min_mcost;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382 int
00383 SubPelBlockSearchBiPred (imgpel* orig_pic,
00384 short ref,
00385 int list,
00386 int pic_pix_x,
00387 int pic_pix_y,
00388 int blocktype,
00389 MotionVector *pred_mv1,
00390 MotionVector *pred_mv2,
00391 MotionVector *mv1,
00392 MotionVector *mv2,
00393 int search_pos2,
00394 int search_pos4,
00395 int min_mcost,
00396 int* lambda,
00397 int apply_weights
00398 )
00399 {
00400 int list_offset = img->mb_data[img->current_mb_nr].list_offset;
00401
00402 int pos, best_pos, mcost;
00403 int cand_mv_x, cand_mv_y;
00404
00405 int blocksize_x = params->blc_size[blocktype][0];
00406 int blocksize_y = params->blc_size[blocktype][1];
00407
00408 int pic4_pix_x = ((pic_pix_x + IMG_PAD_SIZE)<< 2);
00409 int pic4_pix_y = ((pic_pix_y + IMG_PAD_SIZE)<< 2);
00410
00411 int max_pos2 = ( !start_me_refinement_hp ? imax(1,search_pos2) : search_pos2);
00412 int cmv_x, cmv_y;
00413 int smv_x = mv2->mv_x + pic4_pix_x;
00414 int smv_y = mv2->mv_y + pic4_pix_y;
00415
00416 StorablePicture *ref_picture1 = listX[list + list_offset][ref];
00417 StorablePicture *ref_picture2 = listX[(list ^ 1) + list_offset][0];
00418
00419 int lambda_factor = lambda[H_PEL];
00420
00421 ref_pic1_sub.luma = ref_picture1->p_curr_img_sub;
00422 ref_pic2_sub.luma = ref_picture2->p_curr_img_sub;
00423 img_width = ref_picture1->size_x;
00424 img_height = ref_picture1->size_y;
00425 width_pad = ref_picture1->size_x_pad;
00426 height_pad = ref_picture1->size_y_pad;
00427
00428 if (apply_weights)
00429 {
00430 computeBiPred = computeBiPred2[H_PEL];
00431 }
00432 else
00433 {
00434 computeBiPred = computeBiPred1[H_PEL];
00435 }
00436
00437
00438 if ( ChromaMEEnable )
00439 {
00440 ref_pic1_sub.crcb[0] = ref_picture1->imgUV_sub[0];
00441 ref_pic1_sub.crcb[1] = ref_picture1->imgUV_sub[1];
00442 ref_pic2_sub.crcb[0] = ref_picture2->imgUV_sub[0];
00443 ref_pic2_sub.crcb[1] = ref_picture2->imgUV_sub[1];
00444 width_pad_cr = ref_picture1->size_x_cr_pad;
00445 height_pad_cr = ref_picture1->size_y_cr_pad;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455 for (best_pos = 0, pos = start_me_refinement_hp; pos < max_pos2; pos++)
00456 {
00457 cand_mv_x = mv1->mv_x + (spiral_hpel_search_x[pos]);
00458 cand_mv_y = mv1->mv_y + (spiral_hpel_search_y[pos]);
00459
00460
00461 mcost = MV_COST_SMP (lambda_factor, cand_mv_x, cand_mv_y, pred_mv1->mv_x, pred_mv1->mv_y);
00462 mcost += MV_COST_SMP (lambda_factor, mv2->mv_x, mv2->mv_y, pred_mv2->mv_x, pred_mv2->mv_y);
00463
00464 if (mcost >= min_mcost) continue;
00465
00466 cmv_x = cand_mv_x + pic4_pix_x;
00467 cmv_y = cand_mv_y + pic4_pix_y;
00468
00469 mcost += computeBiPred(orig_pic, blocksize_y, blocksize_x,
00470 min_mcost - mcost, cmv_x, cmv_y, smv_x, smv_y);
00471
00472 if (mcost < min_mcost)
00473 {
00474 min_mcost = mcost;
00475 best_pos = pos;
00476 }
00477 }
00478
00479 if (best_pos)
00480 {
00481 mv1->mv_x += (spiral_hpel_search_x [best_pos]);
00482 mv1->mv_y += (spiral_hpel_search_y [best_pos]);
00483 }
00484
00485 computeBiPred = apply_weights? computeBiPred2[Q_PEL] : computeBiPred1[Q_PEL];
00486
00487
00488
00489
00490
00491
00492
00493 if ( !start_me_refinement_qp )
00494 min_mcost = INT_MAX;
00495
00496 lambda_factor = lambda[Q_PEL];
00497
00498
00499 for (best_pos = 0, pos = start_me_refinement_qp; pos < search_pos4; pos++)
00500 {
00501 cand_mv_x = mv1->mv_x + spiral_search_x[pos];
00502 cand_mv_y = mv1->mv_y + spiral_search_y[pos];
00503
00504
00505 mcost = MV_COST_SMP (lambda_factor, cand_mv_x, cand_mv_y, pred_mv1->mv_x, pred_mv1->mv_y);
00506 mcost += MV_COST_SMP (lambda_factor, mv2->mv_x, mv2->mv_y, pred_mv2->mv_x, pred_mv2->mv_y);
00507
00508 if (mcost >= min_mcost) continue;
00509 cmv_x = cand_mv_x + pic4_pix_x;
00510 cmv_y = cand_mv_y + pic4_pix_y;
00511
00512 mcost += computeBiPred(orig_pic, blocksize_y, blocksize_x,
00513 min_mcost - mcost, cmv_x, cmv_y, smv_x, smv_y);
00514
00515 if (mcost < min_mcost)
00516 {
00517 min_mcost = mcost;
00518 best_pos = pos;
00519 }
00520
00521 }
00522
00523 if (best_pos)
00524 {
00525 mv1->mv_x += spiral_search_x [best_pos];
00526 mv1->mv_y += spiral_search_y [best_pos];
00527 }
00528
00529
00530 return min_mcost;
00531 }
00532