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 #include "macroblock.h"
00027 #include "me_distortion.h"
00028 #include "me_fullsearch.h"
00029 #include "mv_search.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038 int
00039 FullPelBlockMotionSearch (Macroblock *currMB ,
00040 MotionVector *pred_mv,
00041 MEBlock *mv_block,
00042 int min_mcost,
00043 int lambda_factor
00044 )
00045 {
00046 ImageParameters *p_Img = currMB->p_Img;
00047 InputParameters *p_Inp = currMB->p_Inp;
00048 Slice *currSlice = currMB->p_slice;
00049 int search_range = mv_block->searchRange.max_x >> 2;
00050
00051 int pos, mcost;
00052 MotionVector cand, center, pred;
00053 short ref = mv_block->ref_idx;
00054
00055 StorablePicture *ref_picture = p_Img->listX[mv_block->list+currMB->list_offset][ref];
00056
00057 int best_pos = 0;
00058 int max_pos = (2*search_range+1)*(2*search_range+1);
00059
00060 MotionVector *mv = &mv_block->mv[(short) mv_block->list];
00061 int check_for_00 = (mv_block->blocktype==1 && !p_Inp->rdopt && currSlice->slice_type!=B_SLICE && ref==0);
00062 center.mv_x = mv_block->pos_x_padded + mv->mv_x;
00063 center.mv_y = mv_block->pos_y_padded + mv->mv_y;
00064 pred.mv_x = mv_block->pos_x_padded + pred_mv->mv_x;
00065 pred.mv_y = mv_block->pos_y_padded + pred_mv->mv_y;
00066
00067
00068
00069 for (pos=0; pos<max_pos; pos++)
00070 {
00071
00072 cand.mv_x = center.mv_x + p_Img->spiral_qpel_search[pos].mv_x;
00073 cand.mv_y = center.mv_y + p_Img->spiral_qpel_search[pos].mv_y;
00074
00075
00076 mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00077
00078 if (check_for_00 && cand.mv_x == mv_block->pos_x_padded && cand.mv_y == mv_block->pos_y_padded)
00079 {
00080 mcost -= WEIGHTED_COST (lambda_factor, 16);
00081 }
00082 if (mcost >= min_mcost) continue;
00083
00084
00085 mcost += mv_block->computePredFPel(ref_picture, mv_block, min_mcost - mcost, &cand);
00086
00087
00088 if (mcost < min_mcost)
00089 {
00090 best_pos = pos;
00091 min_mcost = mcost;
00092 }
00093 }
00094
00095
00096
00097 if (best_pos)
00098 {
00099 add_mvs(mv, &p_Img->spiral_qpel_search[best_pos]);
00100 }
00101 return min_mcost;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110 int
00111 FullPelBlockMotionBiPred (Macroblock *currMB,
00112 int list,
00113 MotionVector *pred_mv1,
00114 MotionVector *pred_mv2,
00115 MotionVector *mv1,
00116 MotionVector *mv2,
00117 MEBlock *mv_block,
00118 int search_range,
00119 int min_mcost,
00120 int lambda_factor
00121 )
00122 {
00123 ImageParameters *p_Img = currMB->p_Img;
00124 short ref = mv_block->ref_idx;
00125 StorablePicture *ref_picture1 = p_Img->listX[list + currMB->list_offset][ref];
00126 StorablePicture *ref_picture2 = p_Img->listX[(list ^ 1) + currMB->list_offset][0];
00127
00128 int pos, mcost;
00129
00130 int best_pos = 0;
00131 int max_pos = (2 * (search_range >> 2) +1)*(2 * (search_range >> 2) + 1);
00132
00133 MotionVector center1, center2, cand, pred1, pred2;
00134 pred1.mv_x = mv_block->pos_x_padded + pred_mv1->mv_x;
00135 pred1.mv_y = mv_block->pos_y_padded + pred_mv1->mv_y;
00136 pred2.mv_x = mv_block->pos_x_padded + pred_mv2->mv_x;
00137 pred2.mv_y = mv_block->pos_y_padded + pred_mv2->mv_y;
00138 center1.mv_x = mv_block->pos_x_padded + mv1->mv_x;
00139 center1.mv_y = mv_block->pos_y_padded + mv1->mv_y;
00140 center2.mv_x = mv_block->pos_x_padded + mv2->mv_x;
00141 center2.mv_y = mv_block->pos_y_padded + mv2->mv_y;
00142
00143
00144
00145 for (pos=0; pos<max_pos; pos++)
00146 {
00147
00148 cand.mv_x = center1.mv_x + (p_Img->spiral_search[pos].mv_x << 2);
00149 cand.mv_y = center1.mv_y + (p_Img->spiral_search[pos].mv_y << 2);
00150
00151
00152 mcost = mv_cost (p_Img, lambda_factor, &cand, &pred1);
00153 mcost += mv_cost (p_Img, lambda_factor, ¢er2, &pred2);
00154
00155 if (mcost >= min_mcost) continue;
00156
00157
00158 mcost += mv_block->computeBiPredFPel(ref_picture1, ref_picture2, mv_block, min_mcost - mcost,
00159 &cand, ¢er2);
00160
00161
00162 if (mcost < min_mcost)
00163 {
00164 best_pos = pos;
00165 min_mcost = mcost;
00166 }
00167 }
00168
00169
00170 if (best_pos)
00171 {
00172 add_mvs(mv1, &p_Img->spiral_search[best_pos]);
00173 }
00174 return min_mcost;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 int
00184 SubPelBlockMotionSearch (Macroblock *currMB,
00185 MotionVector *pred,
00186 MEBlock *mv_block,
00187 int min_mcost,
00188 int* lambda
00189 )
00190 {
00191 Slice *currSlice = currMB->p_slice;
00192 ImageParameters *p_Img = currMB->p_Img;
00193 InputParameters *p_Inp = currMB->p_Inp;
00194
00195 int pos, best_pos, mcost;
00196
00197 MotionVector cand;
00198 int list = mv_block->list;
00199 int cur_list = list + currMB->list_offset;
00200 short ref = mv_block->ref_idx;
00201 StorablePicture *ref_picture = p_Img->listX[cur_list][ref];
00202
00203 MotionVector *mv = &mv_block->mv[list];
00204
00205 int check_position0 = (!p_Inp->rdopt && currSlice->slice_type != B_SLICE && ref==0 && mv_block->blocktype==1 && mv->mv_x == 0 && mv->mv_y ==0);
00206
00207 int max_pos2 = ( !p_Img->start_me_refinement_hp ? imax(1, mv_block->search_pos2) : mv_block->search_pos2);
00208 MotionVector cmv;
00209
00210 int lambda_factor = lambda[H_PEL];
00211
00212
00213
00214
00215
00216
00217
00218
00219 for (best_pos = 0, pos = p_Img->start_me_refinement_hp; pos < max_pos2; pos++)
00220 {
00221 cand.mv_x = mv->mv_x + p_Img->spiral_hpel_search[pos].mv_x;
00222 cand.mv_y = mv->mv_y + p_Img->spiral_hpel_search[pos].mv_y;
00223
00224
00225 mcost = mv_cost (p_Img, lambda_factor, &cand, pred);
00226
00227
00228 if (mcost >= min_mcost) continue;
00229
00230 cmv = pad_MVs(cand, mv_block);
00231
00232 mcost += mv_block->computePredHPel( ref_picture, mv_block, min_mcost - mcost, &cmv);
00233
00234 if (pos==0 && check_position0)
00235 {
00236 mcost -= WEIGHTED_COST (lambda_factor, 16);
00237 }
00238
00239 if (mcost < min_mcost)
00240 {
00241 min_mcost = mcost;
00242 best_pos = pos;
00243 }
00244 }
00245 if (best_pos)
00246 {
00247 mv->mv_x = mv->mv_x + p_Img->spiral_hpel_search[best_pos].mv_x;
00248 mv->mv_y = mv->mv_y + p_Img->spiral_hpel_search[best_pos].mv_y;
00249 }
00250
00251 if ( !p_Img->start_me_refinement_qp )
00252 min_mcost = INT_MAX;
00253
00254
00255
00256
00257
00258
00259
00260 lambda_factor = lambda[Q_PEL];
00261
00262
00263 for (best_pos = 0, pos = p_Img->start_me_refinement_qp; pos < mv_block->search_pos4; pos++)
00264 {
00265 cand.mv_x = mv->mv_x + p_Img->spiral_search[pos].mv_x;
00266 cand.mv_y = mv->mv_y + p_Img->spiral_search[pos].mv_y;
00267
00268
00269 mcost = mv_cost (p_Img, lambda_factor, &cand, pred);
00270
00271 if (mcost >= min_mcost) continue;
00272
00273 cmv = pad_MVs(cand, mv_block);
00274
00275 mcost += mv_block->computePredQPel( ref_picture, mv_block, min_mcost - mcost, &cmv);
00276
00277 if (mcost < min_mcost)
00278 {
00279 min_mcost = mcost;
00280 best_pos = pos;
00281 }
00282 }
00283 if (best_pos)
00284 {
00285 add_mvs(mv, &p_Img->spiral_search[best_pos]);
00286 }
00287
00288
00289 return min_mcost;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298 int
00299 SubPelBlockSearchBiPred (Macroblock *currMB,
00300 MEBlock *mv_block,
00301 int list,
00302 MotionVector *pred_mv1,
00303 MotionVector *pred_mv2,
00304 MotionVector *mv1,
00305 MotionVector *mv2,
00306 int min_mcost,
00307 int* lambda
00308 )
00309 {
00310 ImageParameters *p_Img = currMB->p_Img;
00311
00312 int list_offset = p_Img->mb_data[p_Img->current_mb_nr].list_offset;
00313
00314 int pos, best_pos, mcost;
00315 MotionVector cand;
00316
00317 int max_pos2 = ( !p_Img->start_me_refinement_hp ? imax(1, mv_block->search_pos2) : mv_block->search_pos2);
00318
00319 MotionVector cmv, smv = pad_MVs(*mv2, mv_block);
00320 short ref = mv_block->ref_idx;
00321
00322 StorablePicture *ref_picture1 = p_Img->listX[list + list_offset][ref];
00323 StorablePicture *ref_picture2 = p_Img->listX[(list ^ 1) + list_offset][0];
00324
00325 int lambda_factor = lambda[H_PEL];
00326
00327
00328
00329
00330
00331
00332
00333
00334 for (best_pos = 0, pos = p_Img->start_me_refinement_hp; pos < max_pos2; pos++)
00335 {
00336 cand.mv_x = mv1->mv_x + p_Img->spiral_hpel_search[pos].mv_x;
00337 cand.mv_y = mv1->mv_y + p_Img->spiral_hpel_search[pos].mv_y;
00338
00339
00340 mcost = mv_cost (p_Img, lambda_factor, &cand, pred_mv1);
00341 mcost += mv_cost (p_Img, lambda_factor, mv2, pred_mv2);
00342
00343 if (mcost >= min_mcost) continue;
00344
00345 cmv = pad_MVs(cand, mv_block);
00346 mcost += mv_block->computeBiPredHPel(ref_picture1, ref_picture2, mv_block, min_mcost - mcost, &cmv, &smv);
00347
00348 if (mcost < min_mcost)
00349 {
00350 min_mcost = mcost;
00351 best_pos = pos;
00352 }
00353 }
00354
00355 if (best_pos)
00356 {
00357 add_mvs(mv1, &p_Img->spiral_hpel_search[best_pos]);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366 if ( !p_Img->start_me_refinement_qp )
00367 min_mcost = INT_MAX;
00368
00369 lambda_factor = lambda[Q_PEL];
00370
00371
00372 for (best_pos = 0, pos = p_Img->start_me_refinement_qp; pos < mv_block->search_pos4; pos++)
00373 {
00374 cand.mv_x = mv1->mv_x + p_Img->spiral_search[pos].mv_x;
00375 cand.mv_y = mv1->mv_y + p_Img->spiral_search[pos].mv_y;
00376
00377
00378 mcost = mv_cost (p_Img, lambda_factor, &cand, pred_mv1);
00379 mcost += mv_cost (p_Img, lambda_factor, mv2, pred_mv2);
00380
00381 if (mcost >= min_mcost) continue;
00382
00383 cmv = pad_MVs(cand, mv_block);
00384 mcost += mv_block->computeBiPredQPel(ref_picture1, ref_picture2, mv_block, min_mcost - mcost, &cmv, &smv);
00385
00386 if (mcost < min_mcost)
00387 {
00388 min_mcost = mcost;
00389 best_pos = pos;
00390 }
00391
00392 }
00393
00394 if (best_pos)
00395 {
00396 add_mvs(mv1, &p_Img->spiral_search[best_pos]);
00397 }
00398
00399
00400 return min_mcost;
00401 }
00402