00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "contributors.h"
00018
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_epzs.h"
00029 #include "me_epzs_common.h"
00030 #include "mv_search.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 int
00042 EPZSPelBlockMotionSearch (Macroblock * currMB,
00043 MotionVector * pred_mv,
00044 MEBlock * mv_block,
00045 int min_mcost,
00046 int lambda_factor
00047 )
00048 {
00049 Slice *currSlice = currMB->p_slice;
00050 ImageParameters *p_Img = currMB->p_Img;
00051 InputParameters *p_Inp = currMB->p_Inp;
00052 EPZSParameters *p_EPZS = currSlice->p_EPZS;
00053 PicMotionParams *motion = &p_Img->enc_picture->motion;
00054
00055 int blocktype = mv_block->blocktype;
00056
00057 int list = mv_block->list;
00058 int cur_list = list + currMB->list_offset;
00059 short ref = mv_block->ref_idx;
00060 MotionVector *mv = &mv_block->mv[list];
00061 SearchWindow *searchRange = &mv_block->searchRange;
00062 int mapCenter_x = searchRange->max_x - mv->mv_x;
00063 int mapCenter_y = searchRange->max_y - mv->mv_y;
00064 StorablePicture *ref_picture = p_Img->listX[cur_list][ref];
00065
00066 int lambda_dist = (((lambda_factor) * (2)) >> LAMBDA_ACCURACY_BITS);
00067 int stopCriterion = p_EPZS->medthres[blocktype] + lambda_dist;
00068 int *prevSad = &p_EPZS->distortion[cur_list][blocktype - 1][mv_block->pos_x2];
00069 MotionVector *p_motion = NULL;
00070
00071 EPZSStructure *searchPatternF = p_EPZS->searchPattern;
00072 uint16 **EPZSMap = &p_EPZS->EPZSMap[mapCenter_y];
00073
00074 MotionVector center = pad_MVs (*mv, mv_block);
00075 MotionVector pred = pad_MVs (*pred_mv, mv_block);
00076 MotionVector tmp = *mv, cand = center;
00077
00078 ++p_EPZS->BlkCount;
00079 if (p_EPZS->BlkCount == 0)
00080 ++p_EPZS->BlkCount;
00081
00082 if (p_Inp->EPZSSpatialMem)
00083 {
00084 #if EPZSREF
00085 p_motion = &p_EPZS->p_motion[cur_list][ref][blocktype - 1][mv_block->block_y][mv_block->pos_x2];
00086 #else
00087 p_motion = &p_EPZS->p_motion[cur_list][blocktype - 1][mv_block->block_y][mv_block->pos_x2];
00088 #endif
00089 }
00090
00091
00092
00093
00094
00095 p_EPZS->EPZSMap[searchRange->max_y][searchRange->max_x] = p_EPZS->BlkCount;
00096
00097
00098 min_mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00099
00100
00101 min_mcost += mv_block->computePredFPel (ref_picture, mv_block, INT_MAX, &cand);
00102
00103
00104 if ((ref > 0 && currSlice->structure == FRAME) && (*prevSad < imin (p_EPZS->medthres[blocktype] + lambda_dist, min_mcost)))
00105 {
00106 #if EPZSREF
00107 if (p_Inp->EPZSSpatialMem)
00108 #else
00109 if (p_Inp->EPZSSpatialMem && ref == 0)
00110 #endif
00111 {
00112 *p_motion = tmp;
00113 }
00114 return min_mcost;
00115 }
00116
00117
00118
00119 if (min_mcost > stopCriterion)
00120 {
00121 Boolean checkMedian = FALSE;
00122 int second_mcost = INT_MAX;
00123
00124 int prednum = 5;
00125 int conditionEPZS;
00126 MotionVector tmp2 = {0, 0}, tmv;
00127 int pos, mcost;
00128 short invalid_refs = 0;
00129
00130 stopCriterion = EPZSDetermineStopCriterion (p_EPZS, prevSad, mv_block, lambda_dist);
00131
00132 if (min_mcost < stopCriterion >> 1)
00133 {
00134 #if EPZSREF
00135 if (p_Inp->EPZSSpatialMem)
00136 #else
00137 if (p_Inp->EPZSSpatialMem && ref == 0)
00138 #endif
00139 {
00140 *p_motion = tmp;
00141 }
00142
00143 return min_mcost;
00144 }
00145
00146
00147
00148
00149 invalid_refs = EPZSSpatialPredictors (p_EPZS, mv_block->block,
00150 list, currMB->list_offset, ref, motion->ref_idx[list], motion->mv[list]);
00151
00152 if (p_Inp->EPZSSpatialMem)
00153 EPZSSpatialMemPredictors (p_EPZS, mv_block, cur_list, &prednum, ref_picture->size_x >> 2);
00154
00155
00156 if (p_Inp->EPZSTemporal && blocktype < 5)
00157
00158 {
00159 EPZSTemporalPredictors (currMB, ref_picture, p_EPZS, mv_block, &prednum, stopCriterion, min_mcost);
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 conditionEPZS = ((min_mcost > 3 * stopCriterion) && ((ref < 2 && blocktype < 4) || (ref < 1 && blocktype == 4)
00176 || ((currSlice->structure != FRAME || currMB->list_offset)
00177 && ref < 3))
00178 && (p_Inp->EPZSFixed > 1 || (p_Inp->EPZSFixed && currSlice->slice_type == P_SLICE)));
00179
00180 if (conditionEPZS)
00181 EPZSWindowPredictors (mv, p_EPZS->predictor, &prednum,
00182 (blocktype < 5) && (invalid_refs > 2) && (ref < 1 + (currSlice->structure != FRAME || currMB->list_offset))
00183 ? p_EPZS->window_predictor_ext : p_EPZS->window_predictor);
00184
00185
00186
00187
00188
00189
00190 conditionEPZS = (ref == 0 || (ref > 0 && min_mcost > 2 * stopCriterion));
00191
00192 if (conditionEPZS && currMB->mbAddrX != 0 && p_Inp->EPZSBlockType)
00193 EPZSBlockTypePredictorsMB (currSlice, mv_block, p_EPZS->predictor->point, &prednum);
00194
00195
00196 for (pos = 0; pos < prednum; ++pos)
00197 {
00198 tmv = p_EPZS->predictor->point[pos].motion;
00199
00200 if (iabs (tmv.mv_x - mv->mv_x) <= searchRange->max_x && iabs (tmv.mv_y - mv->mv_y) <= searchRange->max_y)
00201 {
00202 if (EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] != p_EPZS->BlkCount)
00203 {
00204 EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] = p_EPZS->BlkCount;
00205 cand = pad_MVs (tmv, mv_block);
00206
00207
00208 mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00209
00210 if (mcost >= second_mcost)
00211 continue;
00212
00213 mcost += mv_block->computePredFPel (ref_picture, mv_block, second_mcost - mcost, &cand);
00214
00215
00216 if (mcost < min_mcost)
00217 {
00218 tmp2 = tmp;
00219 tmp = tmv;
00220 second_mcost = min_mcost;
00221 min_mcost = mcost;
00222 checkMedian = TRUE;
00223 }
00224
00225 else if (mcost < second_mcost)
00226 {
00227 tmp2 = tmv;
00228 second_mcost = mcost;
00229 checkMedian = TRUE;
00230 }
00231 }
00232 }
00233 }
00234
00235
00236
00237
00238
00239 if (min_mcost > stopCriterion)
00240 {
00241 const int mv_range = 10;
00242 int patternStop = 0, pointNumber = 0, checkPts, nextLast = 0;
00243 int totalCheckPts = 0, motionDirection = 0;
00244
00245
00246 if (p_Inp->EPZSPattern != 0)
00247 {
00248 if ((min_mcost < stopCriterion + ((3 * p_EPZS->medthres[blocktype]) >> 1)))
00249 {
00250 if ((tmp.mv_x == 0 && tmp.mv_y == 0)
00251 || (iabs (tmp.mv_x - mv->mv_x) < (mv_range) && iabs (tmp.mv_y - mv->mv_y) < (mv_range)))
00252 searchPatternF = p_Img->sdiamond;
00253 else
00254 searchPatternF = p_Img->square;
00255 }
00256 else if (blocktype > 4 || (ref > 0 && blocktype != 1))
00257 searchPatternF = p_Img->square;
00258 else
00259 searchPatternF = p_EPZS->searchPattern;
00260 }
00261
00262
00263 center = tmp;
00264
00265 for (;;)
00266 {
00267 totalCheckPts = searchPatternF->searchPoints;
00268 do
00269 {
00270 checkPts = totalCheckPts;
00271 do
00272 {
00273 tmv = add_MVs (center, &(searchPatternF->point[pointNumber].motion));
00274
00275 if ((iabs (tmv.mv_x - mv->mv_x) <= searchRange->max_x) && (iabs (tmv.mv_y - mv->mv_y) <= searchRange->max_y))
00276 {
00277 if (EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] != p_EPZS->BlkCount)
00278 {
00279 EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] = p_EPZS->BlkCount;
00280 cand = pad_MVs (tmv, mv_block);
00281
00282 mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00283
00284 if (mcost < min_mcost)
00285 {
00286 mcost += mv_block->computePredFPel (ref_picture, mv_block, min_mcost - mcost, &cand);
00287
00288 if (mcost < min_mcost)
00289 {
00290 tmp = tmv;
00291 min_mcost = mcost;
00292 motionDirection = pointNumber;
00293 }
00294 }
00295 }
00296 }
00297 ++pointNumber;
00298 if (pointNumber >= searchPatternF->searchPoints)
00299 pointNumber -= searchPatternF->searchPoints;
00300 checkPts--;
00301 }
00302 while (checkPts > 0);
00303
00304 if (nextLast || ((tmp.mv_x == center.mv_x) && (tmp.mv_y == center.mv_y)))
00305 {
00306 patternStop = searchPatternF->stopSearch;
00307 searchPatternF = searchPatternF->nextpattern;
00308 totalCheckPts = searchPatternF->searchPoints;
00309 nextLast = searchPatternF->nextLast;
00310 motionDirection = 0;
00311 pointNumber = 0;
00312 }
00313 else
00314 {
00315 totalCheckPts = searchPatternF->point[motionDirection].next_points;
00316 pointNumber = searchPatternF->point[motionDirection].start_nmbr;
00317 center = tmp;
00318 }
00319 }
00320 while (patternStop != 1);
00321
00322 if ((ref > 0) && (currSlice->structure == FRAME)
00323 && ((4 * *prevSad < min_mcost) || ((3 * *prevSad < min_mcost) && (*prevSad <= stopCriterion))))
00324 {
00325 *mv = tmp;
00326 #if EPZSREF
00327 if (p_Inp->EPZSSpatialMem)
00328 #else
00329 if (p_Inp->EPZSSpatialMem && ref == 0)
00330 #endif
00331 {
00332 *p_motion = tmp;
00333 }
00334
00335 return min_mcost;
00336 }
00337
00338
00339 conditionEPZS = (checkMedian == TRUE)
00340 && ((currSlice->slice_type == P_SLICE) || (blocktype < 5))
00341 && (min_mcost > stopCriterion) && (p_Inp->EPZSDual > 0);
00342
00343 if (!conditionEPZS)
00344 break;
00345
00346 pointNumber = 0;
00347 patternStop = 0;
00348 motionDirection = 0;
00349 nextLast = 0;
00350
00351 if ((tmp.mv_x == 0 && tmp.mv_y == 0) || (tmp.mv_x == mv->mv_x && tmp.mv_y == mv->mv_y))
00352 {
00353 if (iabs (tmp.mv_x - mv->mv_x) < (mv_range) && iabs (tmp.mv_y - mv->mv_y) < (mv_range))
00354 searchPatternF = p_Img->sdiamond;
00355 else
00356 searchPatternF = p_Img->square;
00357 }
00358 else
00359 searchPatternF = p_EPZS->searchPatternD;
00360
00361
00362 center = tmp2;
00363 checkMedian = FALSE;
00364 }
00365 }
00366 }
00367
00368 if ((ref == 0) || (*prevSad > min_mcost))
00369 *prevSad = min_mcost;
00370 #if EPZSREF
00371 if (p_Inp->EPZSSpatialMem)
00372 #else
00373 if (p_Inp->EPZSSpatialMem && ref == 0)
00374 #endif
00375 {
00376 *p_motion = tmp;
00377
00378
00379 }
00380
00381 *mv = tmp;
00382
00383 return min_mcost;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393 int
00394 EPZSPelBlockMotionSearchSubMB (Macroblock * currMB,
00395 MotionVector * pred_mv,
00396 MEBlock * mv_block,
00397 int min_mcost,
00398 int lambda_factor
00399 )
00400 {
00401 Slice *currSlice = currMB->p_slice;
00402 ImageParameters *p_Img = currMB->p_Img;
00403 InputParameters *p_Inp = currMB->p_Inp;
00404 EPZSParameters *p_EPZS = currSlice->p_EPZS;
00405 PicMotionParams *motion = &p_Img->enc_picture->motion;
00406
00407 int blocktype = mv_block->blocktype;
00408 int list = mv_block->list;
00409 int cur_list = list + currMB->list_offset;
00410 short ref = mv_block->ref_idx;
00411 StorablePicture *ref_picture = p_Img->listX[cur_list][ref];
00412
00413 MotionVector *mv = &mv_block->mv[list];
00414 MotionVector center = pad_MVs (*mv, mv_block);
00415 MotionVector cand = center;
00416 MotionVector pred = pad_MVs (*pred_mv, mv_block);
00417 MotionVector tmp = *mv;
00418 SearchWindow *searchRange = &mv_block->searchRange;
00419 int mapCenter_x = searchRange->max_x - mv->mv_x;
00420 int mapCenter_y = searchRange->max_y - mv->mv_y;
00421
00422 short pic_pix_x2 = mv_block->pos_x2;
00423
00424 int lambda_dist = (((lambda_factor) * (3)) >> LAMBDA_ACCURACY_BITS);
00425 int stopCriterion = p_EPZS->medthres[blocktype] + lambda_dist;
00426 int *prevSad = &p_EPZS->distortion[cur_list][blocktype - 1][pic_pix_x2];
00427 MotionVector *p_motion = NULL;
00428
00429 EPZSStructure *searchPatternF = p_EPZS->searchPattern;
00430 uint16 **EPZSMap = &p_EPZS->EPZSMap[mapCenter_y];
00431
00432 ++p_EPZS->BlkCount;
00433 if (p_EPZS->BlkCount == 0)
00434 ++p_EPZS->BlkCount;
00435
00436 if (p_Inp->EPZSSpatialMem)
00437 {
00438 #if EPZSREF
00439 p_motion = &p_EPZS->p_motion[cur_list][ref][blocktype - 1][mv_block->block_y][pic_pix_x2];
00440 #else
00441 p_motion = &p_EPZS->p_motion[cur_list][blocktype - 1][mv_block->block_y][pic_pix_x2];
00442 #endif
00443 }
00444
00445
00446
00447
00448
00449 p_EPZS->EPZSMap[searchRange->max_y][searchRange->max_x] = p_EPZS->BlkCount;
00450
00451
00452 min_mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00453
00454
00455 min_mcost += mv_block->computePredFPel (ref_picture, mv_block, INT_MAX, &cand);
00456
00457
00458 if ((ref > 0 && currSlice->structure == FRAME) && (*prevSad < imin (p_EPZS->medthres[blocktype] + lambda_dist, min_mcost)))
00459 {
00460 #if EPZSREF
00461 if (p_Inp->EPZSSpatialMem)
00462 #else
00463 if (p_Inp->EPZSSpatialMem && ref == 0)
00464 #endif
00465 {
00466 *p_motion = tmp;
00467 }
00468 return min_mcost;
00469 }
00470
00471
00472
00473 if (min_mcost > stopCriterion)
00474 {
00475 Boolean checkMedian = FALSE;
00476 int second_mcost = INT_MAX;
00477 int prednum = 5;
00478 int conditionEPZS;
00479
00480 MotionVector tmv, tmp2 = {0,0};
00481 int pos, mcost;
00482
00483 stopCriterion = EPZSDetermineStopCriterion (p_EPZS, prevSad, mv_block, lambda_dist);
00484
00485 if (min_mcost < (stopCriterion >> 1))
00486 {
00487 #if EPZSREF
00488 if (p_Inp->EPZSSpatialMem)
00489 #else
00490 if (p_Inp->EPZSSpatialMem && ref == 0)
00491 #endif
00492 {
00493 *p_motion = tmp;
00494 }
00495 return min_mcost;
00496 }
00497
00498
00499
00500
00501 EPZSSpatialPredictors (p_EPZS, mv_block->block, list, currMB->list_offset, ref, motion->ref_idx[list], motion->mv[list]);
00502
00503 if (p_Inp->EPZSSpatialMem)
00504 EPZSSpatialMemPredictors (p_EPZS, mv_block, cur_list, &prednum, ref_picture->size_x >> 2);
00505
00506
00507
00508
00509
00510 conditionEPZS = (ref == 0 || (ref > 0 && min_mcost > 2 * stopCriterion));
00511
00512 if (conditionEPZS && currMB->mbAddrX != 0 && p_Inp->EPZSBlockType)
00513 EPZSBlockTypePredictors (currSlice, mv_block, p_EPZS->predictor->point, &prednum);
00514
00515
00516 for (pos = 0; pos < prednum; ++pos)
00517 {
00518 tmv = p_EPZS->predictor->point[pos].motion;
00519
00520 if (iabs (tmv.mv_x - mv->mv_x) <= searchRange->max_x && iabs (tmv.mv_y - mv->mv_y) <= searchRange->max_y)
00521 {
00522 if (EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] != p_EPZS->BlkCount)
00523 {
00524 EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] = p_EPZS->BlkCount;
00525
00526 cand = pad_MVs (tmv, mv_block);
00527
00528
00529 mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00530
00531 if (mcost >= second_mcost)
00532 continue;
00533
00534 mcost += mv_block->computePredFPel (ref_picture, mv_block, second_mcost - mcost, &cand);
00535
00536
00537 if (mcost < min_mcost)
00538 {
00539 tmp2 = tmp;
00540 tmp = tmv;
00541 second_mcost = min_mcost;
00542 min_mcost = mcost;
00543 checkMedian = TRUE;
00544 }
00545
00546 else if (mcost < second_mcost)
00547 {
00548 tmp2 = tmv;
00549 second_mcost = mcost;
00550 checkMedian = TRUE;
00551 }
00552 }
00553 }
00554
00555
00556
00557 if (min_mcost < ((3 * stopCriterion) >> 2))
00558 {
00559 #if EPZSREF
00560 if (p_Inp->EPZSSpatialMem)
00561 #else
00562 if (p_Inp->EPZSSpatialMem && ref == 0)
00563 #endif
00564 {
00565 *p_motion = tmp;
00566 }
00567 *mv = tmp;
00568 return min_mcost;
00569 }
00570 }
00571
00572
00573
00574
00575
00576 if (min_mcost > stopCriterion)
00577 {
00578 int patternStop = 0, pointNumber = 0, checkPts, nextLast = 0;
00579 int totalCheckPts = 0, motionDirection = 0;
00580 const int mv_range = 12;
00581
00582
00583 if (p_Inp->EPZSPattern != 0)
00584 {
00585 if ((min_mcost < stopCriterion + ((3 * p_EPZS->medthres[blocktype]) >> 1)))
00586 {
00587 if ((tmp.mv_x == 0 && tmp.mv_y == 0) || (iabs (tmp.mv_x - mv->mv_x) < (mv_range) && iabs (tmp.mv_y - mv->mv_y) < (mv_range)))
00588 searchPatternF = p_Img->sdiamond;
00589 else
00590 searchPatternF = p_Img->square;
00591 }
00592 else
00593 searchPatternF = p_Img->square;
00594 }
00595
00596
00597 center = tmp;
00598 for (;;)
00599 {
00600 totalCheckPts = searchPatternF->searchPoints;
00601 do
00602 {
00603 checkPts = totalCheckPts;
00604 do
00605 {
00606 tmv = add_MVs (center, &(searchPatternF->point[pointNumber].motion));
00607
00608 if ((iabs (tmv.mv_x - mv->mv_x) <= searchRange->max_x) && (iabs (tmv.mv_y - mv->mv_y) <= searchRange->max_y))
00609 {
00610 if (EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] != p_EPZS->BlkCount)
00611 {
00612 EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] = p_EPZS->BlkCount;
00613 cand = pad_MVs(tmv, mv_block);
00614
00615 mcost = mv_cost (p_Img, lambda_factor, &cand, &pred);
00616 if (mcost < min_mcost)
00617 {
00618
00619 mcost += mv_block->computePredFPel (ref_picture, mv_block, min_mcost - mcost, &cand);
00620
00621 if (mcost < min_mcost)
00622 {
00623 tmp = tmv;
00624 min_mcost = mcost;
00625 motionDirection = pointNumber;
00626 }
00627 }
00628 }
00629 }
00630 ++pointNumber;
00631 if (pointNumber >= searchPatternF->searchPoints)
00632 pointNumber -= searchPatternF->searchPoints;
00633 checkPts--;
00634 }
00635 while (checkPts > 0);
00636
00637 if (nextLast || ((tmp.mv_x == center.mv_x) && (tmp.mv_y == center.mv_y)))
00638 {
00639 patternStop = searchPatternF->stopSearch;
00640 searchPatternF = searchPatternF->nextpattern;
00641 totalCheckPts = searchPatternF->searchPoints;
00642 nextLast = searchPatternF->nextLast;
00643 motionDirection = 0;
00644 pointNumber = 0;
00645 }
00646 else
00647 {
00648 totalCheckPts = searchPatternF->point[motionDirection].next_points;
00649 pointNumber = searchPatternF->point[motionDirection].start_nmbr;
00650 center = tmp;
00651 }
00652 }
00653 while (patternStop != 1);
00654
00655 if ((ref > 0) && (currSlice->structure == FRAME)
00656 && ((4 * *prevSad < min_mcost) || ((3 * *prevSad < min_mcost) && (*prevSad <= stopCriterion))))
00657 {
00658 *mv = tmp;
00659 #if EPZSREF
00660 if (p_Inp->EPZSSpatialMem)
00661 #else
00662 if (p_Inp->EPZSSpatialMem && ref == 0)
00663 #endif
00664 {
00665 *p_motion = tmp;
00666 }
00667
00668 return min_mcost;
00669 }
00670
00671
00672 conditionEPZS = (checkMedian == TRUE)
00673 && ((currSlice->slice_type == P_SLICE))
00674 && (min_mcost > stopCriterion) && (p_Inp->EPZSDual > 0);
00675
00676 if (!conditionEPZS)
00677 break;
00678
00679 pointNumber = 0;
00680 patternStop = 0;
00681 motionDirection = 0;
00682 nextLast = 0;
00683
00684 if ((tmp.mv_x == 0 && tmp.mv_y == 0) || (tmp.mv_x == mv->mv_x && tmp.mv_y == mv->mv_y))
00685 {
00686 if (iabs (tmp.mv_x - mv->mv_x) < (mv_range) && iabs (tmp.mv_y - mv->mv_y) < (mv_range))
00687 searchPatternF = p_Img->sdiamond;
00688 else
00689 searchPatternF = p_Img->square;
00690 }
00691 else
00692 searchPatternF = p_EPZS->searchPatternD;
00693
00694
00695 center = tmp2;
00696 checkMedian = FALSE;
00697 }
00698 }
00699 }
00700
00701 if ((ref == 0) || (*prevSad > min_mcost))
00702 *prevSad = min_mcost;
00703
00704 #if EPZSREF
00705 if (p_Inp->EPZSSpatialMem)
00706 #else
00707 if (p_Inp->EPZSSpatialMem && ref == 0)
00708 #endif
00709 {
00710 *p_motion = tmp;
00711 }
00712
00713 *mv = tmp;
00714
00715 return min_mcost;
00716 }
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 int
00728 EPZSBiPredBlockMotionSearch (Macroblock * currMB,
00729 int list,
00730 MotionVector * pred_mv1,
00731 MotionVector * pred_mv2,
00732 MotionVector * mv1,
00733 MotionVector * mv2,
00734 MEBlock * mv_block,
00735 int search_range,
00736 int min_mcost,
00737 int lambda_factor
00738 )
00739 {
00740 Slice *currSlice = currMB->p_slice;
00741 ImageParameters *p_Img = currMB->p_Img;
00742 InputParameters *p_Inp = currMB->p_Inp;
00743 EPZSParameters *p_EPZS = currSlice->p_EPZS;
00744 PicMotionParams *motion = &p_Img->enc_picture->motion;
00745
00746 int blocktype = mv_block->blocktype;
00747 short ref = mv_block->ref_idx;
00748
00749 StorablePicture *ref_picture1 = p_Img->listX[list + currMB->list_offset][ref];
00750 StorablePicture *ref_picture2 = p_Img->listX[(list ^ 1) + currMB->list_offset][0];
00751
00752 int mapCenter_x = search_range - mv1->mv_x;
00753 int mapCenter_y = search_range - mv1->mv_y;
00754
00755 int lambda_dist = (((lambda_factor) * (4)) >> LAMBDA_ACCURACY_BITS);
00756 int stopCriterion = p_EPZS->medthres[blocktype] + lambda_dist;
00757
00758 int *prevSad = &p_EPZS->bi_distortion[list + currMB->list_offset][blocktype - 1][mv_block->pos_x2];
00759 EPZSStructure *searchPatternF = p_EPZS->searchPattern;
00760 uint16 **EPZSMap = &p_EPZS->EPZSMap[mapCenter_y];
00761
00762 MotionVector tmp = *mv1;
00763 MotionVector center1 = pad_MVs (*mv1, mv_block);
00764 MotionVector center2 = pad_MVs (*mv2, mv_block);
00765 MotionVector pred1 = pad_MVs (*pred_mv1, mv_block);
00766 MotionVector pred2 = pad_MVs (*pred_mv2, mv_block);
00767 MotionVector cand1 = center1;
00768 MotionVector cand2 = center2;
00769
00770 ++p_EPZS->BlkCount;
00771 if (p_EPZS->BlkCount == 0)
00772 ++p_EPZS->BlkCount;
00773
00774
00775
00776
00777
00778
00779 p_EPZS->EPZSMap[search_range][search_range] = p_EPZS->BlkCount;
00780
00781
00782 min_mcost = mv_cost (p_Img, lambda_factor, &cand1, &pred1);
00783 min_mcost += mv_cost (p_Img, lambda_factor, &cand2, &pred2);
00784
00785
00786 min_mcost += mv_block->computeBiPredFPel (ref_picture1, ref_picture2, mv_block, INT_MAX, &cand1, &cand2);
00787
00788
00789 if (min_mcost > stopCriterion)
00790 {
00791 Boolean checkMedian = FALSE;
00792 int second_mcost = INT_MAX;
00793 int prednum = 5;
00794 MotionVector tmv, tmp2 = { 0, 0 };
00795 int pos, mcost;
00796
00797 stopCriterion = EPZSDetermineStopCriterion (p_EPZS, prevSad, mv_block, lambda_dist);
00798
00799
00800
00801
00802 EPZSSpatialPredictors (p_EPZS, mv_block->block, list, currMB->list_offset, ref, motion->ref_idx[list], motion->mv[list]);
00803
00804
00805 for (pos = 0; pos < prednum; ++pos)
00806 {
00807 tmv = p_EPZS->predictor->point[pos].motion;
00808
00809 if (iabs (tmv.mv_x - mv1->mv_x) <= search_range && iabs (tmv.mv_y - mv1->mv_y) <= search_range)
00810 {
00811 if (EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] != p_EPZS->BlkCount)
00812 {
00813 EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] = p_EPZS->BlkCount;
00814
00815 cand1 = pad_MVs (tmv, mv_block);
00816
00817
00818 mcost = mv_cost (p_Img, lambda_factor, &cand1, &pred1);
00819 mcost += mv_cost (p_Img, lambda_factor, &cand2, &pred2);
00820
00821 if (mcost >= second_mcost)
00822 continue;
00823
00824 mcost += mv_block->computeBiPredFPel (ref_picture1, ref_picture2, mv_block, second_mcost - mcost, &cand1, &cand2);
00825
00826
00827 if (mcost < min_mcost)
00828 {
00829 tmp2 = tmp;
00830 tmp = tmv;
00831 second_mcost = min_mcost;
00832 min_mcost = mcost;
00833 checkMedian = TRUE;
00834 }
00835
00836 else if (mcost < second_mcost)
00837 {
00838 tmp2 = tmv;
00839 second_mcost = mcost;
00840 checkMedian = TRUE;
00841 }
00842 }
00843 }
00844 }
00845
00846
00847
00848
00849
00850 if (min_mcost > stopCriterion)
00851 {
00852 int conditionEPZS;
00853 int patternStop = 0, pointNumber = 0, checkPts, nextLast = 0;
00854 int totalCheckPts = 0, motionDirection = 0;
00855
00856 const int mv_range = 12;
00857
00858
00859 if (p_Inp->EPZSPattern != 0)
00860 {
00861 if ((min_mcost < stopCriterion + ((4 * p_EPZS->medthres[blocktype]) >> 1)))
00862 {
00863 if ((tmp.mv_x == 0 && tmp.mv_y == 0) || (iabs (tmp.mv_x - mv1->mv_x) < (mv_range) && iabs (tmp.mv_y - mv1->mv_y) < (mv_range)))
00864 searchPatternF = p_Img->sdiamond;
00865 else
00866 searchPatternF = p_Img->square;
00867 }
00868 else if (blocktype > 5 || (ref > 0 && blocktype != 1))
00869 searchPatternF = p_Img->square;
00870 else
00871 searchPatternF = p_EPZS->searchPattern;
00872 }
00873
00874
00875 center1 = tmp;
00876 for (;;)
00877 {
00878 totalCheckPts = searchPatternF->searchPoints;
00879 do
00880 {
00881 checkPts = totalCheckPts;
00882 do
00883 {
00884 tmv = add_MVs (center1, &(searchPatternF->point[pointNumber].motion));
00885
00886 if ((iabs (tmv.mv_x - mv1->mv_x) <= search_range) && (iabs (tmv.mv_y - mv1->mv_y) <= search_range))
00887 {
00888 if (EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] != p_EPZS->BlkCount)
00889 {
00890 EPZSMap[tmv.mv_y][mapCenter_x + tmv.mv_x] = p_EPZS->BlkCount;
00891 cand1 = pad_MVs (tmv, mv_block);
00892
00893 mcost = mv_cost (p_Img, lambda_factor, &cand1, &pred1);
00894 mcost += mv_cost (p_Img, lambda_factor, &cand2, &pred2);
00895
00896 if (mcost < min_mcost)
00897 {
00898 mcost += mv_block->computeBiPredFPel (ref_picture1, ref_picture2, mv_block, min_mcost - mcost, &cand1, &cand2);
00899
00900 if (mcost < min_mcost)
00901 {
00902 tmp = tmv;
00903 min_mcost = mcost;
00904 motionDirection = pointNumber;
00905 }
00906 }
00907 }
00908 }
00909 ++pointNumber;
00910 if (pointNumber >= searchPatternF->searchPoints)
00911 pointNumber -= searchPatternF->searchPoints;
00912 checkPts--;
00913 }
00914 while (checkPts > 0);
00915
00916 if (nextLast || ((tmp.mv_x == center1.mv_x) && (tmp.mv_y == center1.mv_y)))
00917 {
00918 patternStop = searchPatternF->stopSearch;
00919 searchPatternF = searchPatternF->nextpattern;
00920 totalCheckPts = searchPatternF->searchPoints;
00921 nextLast = searchPatternF->nextLast;
00922 motionDirection = 0;
00923 pointNumber = 0;
00924 }
00925 else
00926 {
00927 totalCheckPts = searchPatternF->point[motionDirection].next_points;
00928 pointNumber = searchPatternF->point[motionDirection].start_nmbr;
00929 center1 = tmp;
00930 }
00931 }
00932 while (patternStop != 1);
00933
00934
00935 conditionEPZS = (checkMedian == TRUE) && (blocktype < 5) && (min_mcost > stopCriterion) && (p_Inp->EPZSDual > 0);
00936
00937 if (!conditionEPZS)
00938 break;
00939
00940 pointNumber = 0;
00941 patternStop = 0;
00942 motionDirection = 0;
00943 nextLast = 0;
00944
00945 if ((tmp.mv_x == 0 && tmp.mv_y == 0) || (tmp.mv_x == mv1->mv_x && tmp.mv_y == mv1->mv_y))
00946 {
00947 if (iabs (tmp.mv_x - mv1->mv_x) < (mv_range) && iabs (tmp.mv_y - mv1->mv_y) < (mv_range))
00948 searchPatternF = p_Img->sdiamond;
00949 else
00950 searchPatternF = p_Img->square;
00951 }
00952 else
00953 searchPatternF = p_EPZS->searchPatternD;
00954 totalCheckPts = searchPatternF->searchPoints;
00955
00956
00957 center1 = tmp2;
00958 checkMedian = FALSE;
00959 }
00960 }
00961 }
00962
00963 if (mv_block->iteration_no == 0)
00964 {
00965 *prevSad = min_mcost;
00966 }
00967
00968 *mv1 = tmp;
00969
00970 return min_mcost;
00971 }
00972