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