00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "contributors.h"
00025
00026 #include <math.h>
00027 #include <limits.h>
00028 #include <time.h>
00029
00030 #include "global.h"
00031
00032 #include "image.h"
00033 #include "mv_search.h"
00034 #include "refbuf.h"
00035 #include "memalloc.h"
00036 #include "mb_access.h"
00037 #include "macroblock.h"
00038 #include "mc_prediction.h"
00039 #include "conformance.h"
00040
00041
00042 #include "me_distortion.h"
00043
00044
00045 #include "me_epzs.h"
00046 #include "me_epzs_int.h"
00047 #include "me_fullfast.h"
00048 #include "me_fullsearch.h"
00049 #include "me_umhex.h"
00050 #include "me_umhexsmp.h"
00051 #include "rdoq.h"
00052
00053
00054 static const short bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
00055 static const short by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}};
00056
00057
00058 static int GetSkipCostMB (Macroblock *currMB);
00059 static int BiPredBlockMotionSearch(Macroblock *currMB, MEBlock *, MotionVector*, int, int , int*);
00060
00061
00062
00063
00064
00065
00066
00067
00068 void get_search_range(MEBlock *mv_block, InputParameters *p_Inp, short ref, int blocktype)
00069 {
00070 mv_block->searchRange = mv_block->p_Img->searchRange;
00071
00072 if (p_Inp->full_search == 1)
00073 {
00074 int scale = (imin(ref,1)+1);
00075 mv_block->searchRange.min_x /= scale;
00076 mv_block->searchRange.max_x /= scale;
00077 mv_block->searchRange.min_y /= scale;
00078 mv_block->searchRange.max_y /= scale;
00079 }
00080 else if (p_Inp->full_search != 2)
00081 {
00082 int scale = ((imin(ref,1)+1) * imin(2,blocktype));
00083 mv_block->searchRange.min_x /= scale;
00084 mv_block->searchRange.max_x /= scale;
00085 mv_block->searchRange.min_y /= scale;
00086 mv_block->searchRange.max_y /= scale;
00087 }
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 static inline void set_me_parameters( char **ref_array, short ***mv_array ,short *all_mv, short ref, int step_h, int step_v, int pic_block_x)
00097 {
00098 int i, j;
00099 for (j = 0; j < step_v; j++)
00100 {
00101 memset(&ref_array [j][pic_block_x], ref, step_h * sizeof(char));
00102 }
00103
00104
00105 for (i=pic_block_x; i<pic_block_x + step_h; i++)
00106 {
00107 memcpy(mv_array [0][i], all_mv, 2* sizeof(short));
00108 }
00109
00110 for (j = 1; j < step_v; j++)
00111 {
00112 memcpy(mv_array [j][pic_block_x], mv_array [j - 1][pic_block_x], 2 * step_h * sizeof(short));
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 void set_access_method(int *access_method, MotionVector *blk, int min_x, int min_y, int max_x, int max_y)
00123 {
00124 if ( (blk->mv_x > min_x) && (blk->mv_x < max_x) && (blk->mv_y > min_y) && (blk->mv_y < max_y))
00125 {
00126 *access_method = FAST_ACCESS;
00127 }
00128 else
00129 {
00130 *access_method = UMV_ACCESS;
00131 }
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 void init_ME_engine(Macroblock *currMB)
00141 {
00142 InputParameters *p_Inp = currMB->p_Inp;
00143 switch (p_Inp->SearchMode)
00144 {
00145 case EPZS:
00146 if (p_Inp->EPZSSubPelGrid)
00147 {
00148 currMB->IntPelME = EPZSIntPelBlockMotionSearch;
00149 currMB->BiPredME = EPZSIntBiPredBlockMotionSearch;
00150 currMB->SubPelBiPredME = (p_Inp->EPZSSubPelMEBiPred) ? EPZSSubPelBlockSearchBiPred : SubPelBlockSearchBiPred;
00151 currMB->SubPelME = (p_Inp->EPZSSubPelME) ? EPZSSubPelBlockMotionSearch : SubPelBlockMotionSearch;
00152 }
00153 else
00154 {
00155 currMB->IntPelME = EPZSPelBlockMotionSearch;
00156 currMB->BiPredME = EPZSBiPredBlockMotionSearch;
00157 currMB->SubPelBiPredME = (p_Inp->EPZSSubPelMEBiPred) ? EPZSSubPelBlockSearchBiPred : SubPelBlockSearchBiPred;
00158 currMB->SubPelME = (p_Inp->EPZSSubPelME) ? EPZSSubPelBlockMotionSearch : SubPelBlockMotionSearch;
00159 }
00160 break;
00161 case UM_HEX:
00162 currMB->IntPelME = UMHEXIntegerPelBlockMotionSearch;
00163 currMB->BiPredME = UMHEXBipredIntegerPelBlockMotionSearch;
00164 currMB->SubPelBiPredME = SubPelBlockSearchBiPred;
00165 currMB->SubPelME = UMHEXSubPelBlockME;
00166 break;
00167 case UM_HEX_SIMPLE:
00168 currMB->IntPelME = smpUMHEXIntegerPelBlockMotionSearch;
00169 currMB->BiPredME = smpUMHEXBipredIntegerPelBlockMotionSearch;
00170 currMB->SubPelBiPredME = SubPelBlockSearchBiPred;
00171 currMB->SubPelME = smpUMHEXSubPelBlockME;
00172 break;
00173 case FULL_SEARCH:
00174 currMB->IntPelME = FullPelBlockMotionSearch;
00175 currMB->BiPredME = FullPelBlockMotionBiPred;
00176 currMB->SubPelBiPredME = SubPelBlockSearchBiPred;
00177 currMB->SubPelME = SubPelBlockMotionSearch;
00178 break;
00179 case FAST_FULL_SEARCH:
00180 default:
00181 currMB->IntPelME = FastFullPelBlockMotionSearch;
00182 currMB->BiPredME = FullPelBlockMotionBiPred;
00183 currMB->SubPelBiPredME = SubPelBlockSearchBiPred;
00184 currMB->SubPelME = SubPelBlockMotionSearch;
00185 break;
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 void PrepareMEParams(Slice *currSlice, MEBlock *mv_block, int ChromaMEEnable, int list, int ref)
00196 {
00197 if (mv_block->apply_weights)
00198 {
00199 mv_block->weight_luma = currSlice->wp_weight[list][ref][0];
00200 mv_block->offset_luma = currSlice->wp_offset[list][ref][0];
00201
00202 if ( ChromaMEEnable)
00203 {
00204 mv_block->weight_cr[0] = currSlice->wp_weight[list][ref][1];
00205 mv_block->weight_cr[1] = currSlice->wp_weight[list][ref][2];
00206 mv_block->offset_cr[0] = currSlice->wp_offset[list][ref][1];
00207 mv_block->offset_cr[1] = currSlice->wp_offset[list][ref][2];
00208 }
00209 }
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 void PrepareBiPredMEParams(Slice *currSlice, MEBlock *mv_block, int ChromaMEEnable, int list, int list_offset, int ref)
00219 {
00220 if (mv_block->apply_weights)
00221 {
00222 if (list == LIST_0)
00223 {
00224 mv_block->weight1 = currSlice->wbp_weight[list_offset ][ref][0][0];
00225 mv_block->weight2 = currSlice->wbp_weight[list_offset + LIST_1][ref][0][0];
00226 mv_block->offsetBi = (currSlice->wp_offset[list_offset ][ref][0] + currSlice->wp_offset[list_offset + LIST_1][ref][0] + 1)>>1;
00227
00228 if ( ChromaMEEnable)
00229 {
00230 mv_block->weight1_cr[0] = currSlice->wbp_weight[list_offset ][ref][0][1];
00231 mv_block->weight1_cr[1] = currSlice->wbp_weight[list_offset ][ref][0][2];
00232 mv_block->weight2_cr[0] = currSlice->wbp_weight[list_offset + LIST_1][ref][0][1];
00233 mv_block->weight2_cr[1] = currSlice->wbp_weight[list_offset + LIST_1][ref][0][2];
00234
00235 mv_block->offsetBi_cr[0] = (currSlice->wp_offset[list_offset ][ref][1] + currSlice->wp_offset[list_offset + LIST_1][ref][1] + 1) >> 1;
00236 mv_block->offsetBi_cr[1] = (currSlice->wp_offset[list_offset ][ref][2] + currSlice->wp_offset[list_offset + LIST_1][ref][2] + 1) >> 1;
00237 }
00238 }
00239 else
00240 {
00241 mv_block->weight1 = currSlice->wbp_weight[list_offset + LIST_1][0 ][ref][0];
00242 mv_block->weight2 = currSlice->wbp_weight[list_offset ][0 ][ref][0];
00243 mv_block->offsetBi = (currSlice->wp_offset[list_offset + LIST_1][0][0] + currSlice->wp_offset[list_offset][0][0] + 1)>>1;
00244
00245 if ( ChromaMEEnable)
00246 {
00247 mv_block->weight1_cr[0] = currSlice->wbp_weight[list_offset + LIST_1][0 ][ref][1];
00248 mv_block->weight1_cr[1] = currSlice->wbp_weight[list_offset + LIST_1][0 ][ref][2];
00249 mv_block->weight2_cr[0] = currSlice->wbp_weight[list_offset ][0 ][ref][1];
00250 mv_block->weight2_cr[1] = currSlice->wbp_weight[list_offset ][0 ][ref][2];
00251
00252 mv_block->offsetBi_cr[0] = (currSlice->wp_offset[list_offset + LIST_1][0 ][1] + currSlice->wp_offset[list_offset ][0 ][1] + 1) >> 1;
00253 mv_block->offsetBi_cr[1] = (currSlice->wp_offset[list_offset + LIST_1][0 ][2] + currSlice->wp_offset[list_offset ][0 ][2] + 1) >> 1;
00254 }
00255 }
00256 }
00257 else
00258 {
00259 mv_block->weight1 = (short) (1 << currSlice->luma_log_weight_denom);
00260 mv_block->weight2 = (short) (1 << currSlice->luma_log_weight_denom);
00261 mv_block->offsetBi = 0;
00262 if ( ChromaMEEnable)
00263 {
00264 mv_block->weight1_cr[0] = 1<<currSlice->chroma_log_weight_denom;
00265 mv_block->weight1_cr[1] = 1<<currSlice->chroma_log_weight_denom;
00266 mv_block->weight2_cr[0] = 1<<currSlice->chroma_log_weight_denom;
00267 mv_block->weight2_cr[1] = 1<<currSlice->chroma_log_weight_denom;
00268 mv_block->offsetBi_cr[0] = 0;
00269 mv_block->offsetBi_cr[1] = 0;
00270 }
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279
00280 void get_neighbors(Macroblock *currMB,
00281 PixelPos *block,
00282 int mb_x,
00283 int mb_y,
00284 int blockshape_x
00285 )
00286 {
00287 ImageParameters *p_Img = currMB->p_Img;
00288 int *mb_size = p_Img->mb_size[IS_LUMA];
00289
00290 get4x4Neighbour(currMB, mb_x - 1, mb_y , mb_size, &block[0]);
00291 get4x4Neighbour(currMB, mb_x, mb_y - 1, mb_size, &block[1]);
00292 get4x4Neighbour(currMB, mb_x + blockshape_x, mb_y - 1, mb_size, &block[2]);
00293 get4x4Neighbour(currMB, mb_x - 1, mb_y - 1, mb_size, &block[3]);
00294
00295 if (mb_y > 0)
00296 {
00297 if (mb_x < 8)
00298 {
00299 if (mb_y == 8 )
00300 {
00301 if (blockshape_x == MB_BLOCK_SIZE)
00302 block[2].available = 0;
00303 }
00304 else if (mb_x + blockshape_x == 8)
00305 {
00306 block[2].available = 0;
00307 }
00308 }
00309 else if (mb_x + blockshape_x == MB_BLOCK_SIZE)
00310 {
00311 block[2].available = 0;
00312 }
00313 }
00314
00315 if (!block[2].available)
00316 {
00317 block[2] = block[3];
00318 }
00319 }
00320
00321
00322
00323
00324
00325
00326
00327 void Init_Motion_Search_Module (ImageParameters *p_Img, InputParameters *p_Inp)
00328 {
00329 int bits;
00330 int i_min, i_max,k;
00331 int i, l;
00332
00333 int search_range = p_Inp->search_range;
00334 int max_search_points = imax(9, (2 * search_range + 1) * (2 * search_range + 1));
00335 int max_ref_bits = 1 + 2 * (int)floor(log(imax(16, p_Img->max_num_references + 1)) / log(2) + 1e-10);
00336 int max_ref = (1<<((max_ref_bits>>1)+1))-1;
00337 int number_of_subpel_positions = 4 * (2*search_range+3);
00338 int max_mv_bits = 3 + 2 * (int)ceil (log(number_of_subpel_positions + 1) / log(2) + 1e-10);
00339 int max_mvd = (1<<( max_mv_bits >>1) ) - 1;
00340
00341 p_Img->imgpel_abs_range = (imax(p_Img->max_pel_value_comp[0],p_Img->max_pel_value_comp[1]) + 1) * 64;
00342
00343
00344
00345 if ((p_Img->spiral_search = (MotionVector*)calloc(max_search_points, sizeof(MotionVector))) == NULL)
00346 no_mem_exit("Init_Motion_Search_Module: p_Img->spiral_search");
00347 if ((p_Img->spiral_hpel_search = (MotionVector*)calloc(max_search_points, sizeof(MotionVector))) == NULL)
00348 no_mem_exit("Init_Motion_Search_Module: p_Img->spiral_hpel_search");
00349 if ((p_Img->spiral_qpel_search = (MotionVector*)calloc(max_search_points, sizeof(MotionVector))) == NULL)
00350 no_mem_exit("Init_Motion_Search_Module: p_Img->spiral_qpel_search");
00351
00352 if ((p_Img->mvbits = (int*)calloc(2 * max_mvd + 1, sizeof(int))) == NULL)
00353 no_mem_exit("Init_Motion_Search_Module: p_Img->mvbits");
00354
00355 if ((p_Img->refbits = (int*)calloc(max_ref, sizeof(int))) == NULL)
00356 no_mem_exit("Init_Motion_Search_Module: p_Img->refbits");
00357
00358 #if (JM_MEM_DISTORTION)
00359 if ((p_Img->imgpel_abs = (int*)calloc(p_Img->imgpel_abs_range, sizeof(int))) == NULL)
00360 no_mem_exit("Init_Motion_Search_Module: p_Img->imgpel_abs");
00361 if ((p_Img->imgpel_quad = (int*)calloc(p_Img->imgpel_abs_range, sizeof(int))) == NULL)
00362 no_mem_exit("Init_Motion_Search_Module: p_Img->imgpel_quad");
00363 p_Img->imgpel_abs += p_Img->imgpel_abs_range / 2;
00364 p_Img->imgpel_quad += p_Img->imgpel_abs_range / 2;
00365 #endif
00366
00367 if (p_Img->max_num_references)
00368 get_mem4Dint (&p_Img->motion_cost, 8, 2, p_Img->max_num_references, 4);
00369
00370
00371 p_Img->mvbits += max_mvd;
00372
00373
00374
00375
00376 p_Img->mvbits[0] = 1;
00377 for (bits = 3; bits <= max_mv_bits; bits += 2)
00378 {
00379 i_max = (short) (1 << (bits >> 1));
00380 i_min = i_max >> 1;
00381
00382 for (i = i_min; i < i_max; i++)
00383 p_Img->mvbits[-i] = p_Img->mvbits[i] = bits;
00384 }
00385
00386
00387 p_Img->refbits[0] = 1;
00388 for (bits=3; bits<=max_ref_bits; bits+=2)
00389 {
00390 i_max = (short) (1 << ((bits >> 1) + 1)) - 1;
00391 i_min = i_max >> 1;
00392
00393 for (i = i_min; i < i_max; i++)
00394 p_Img->refbits[i] = bits;
00395 }
00396
00397 #if (JM_MEM_DISTORTION)
00398
00399 p_Img->imgpel_abs[0] = 0;
00400
00401 for (i=1; i<p_Img->imgpel_abs_range / 2; i++)
00402 {
00403 p_Img->imgpel_abs[i] = p_Img->imgpel_abs[-i] = i;
00404 }
00405
00406
00407 p_Img->imgpel_quad[0] = 0;
00408
00409 for (i=1; i<p_Img->imgpel_abs_range / 2; i++)
00410 {
00411 p_Img->imgpel_quad[i] = p_Img->imgpel_quad[-i] = i * i;
00412 }
00413 #endif
00414
00415
00416 p_Img->spiral_search[0].mv_x = p_Img->spiral_search[0].mv_y = 0;
00417 p_Img->spiral_hpel_search[0].mv_x = p_Img->spiral_hpel_search[0].mv_y = 0;
00418 p_Img->spiral_qpel_search[0].mv_x = p_Img->spiral_qpel_search[0].mv_y = 0;
00419
00420 for (k=1, l=1; l <= imax(1,search_range); l++)
00421 {
00422 for (i=-l+1; i< l; i++)
00423 {
00424 p_Img->spiral_search[k].mv_x = (short) i;
00425 p_Img->spiral_search[k].mv_y = (short) -l;
00426 p_Img->spiral_hpel_search[k].mv_x = (short) (i<<1);
00427 p_Img->spiral_hpel_search[k].mv_y = (short) -(l<<1);
00428 p_Img->spiral_qpel_search[k].mv_x = (short) (i<<2);
00429 p_Img->spiral_qpel_search[k++].mv_y = (short) -(l<<2);
00430 p_Img->spiral_search[k].mv_x = (short) i;
00431 p_Img->spiral_search[k].mv_y = (short) l;
00432 p_Img->spiral_hpel_search[k].mv_x = (short) (i<<1);
00433 p_Img->spiral_hpel_search[k].mv_y = (short) (l<<1);
00434 p_Img->spiral_qpel_search[k].mv_x = (short) (i<<2);
00435 p_Img->spiral_qpel_search[k++].mv_y = (short) (l<<2);
00436 }
00437 for (i=-l; i<=l; i++)
00438 {
00439 p_Img->spiral_search[k].mv_x = (short) -l;
00440 p_Img->spiral_search[k].mv_y = (short) i;
00441 p_Img->spiral_hpel_search[k].mv_x = (short) -(l<<1);
00442 p_Img->spiral_hpel_search[k].mv_y = (short) (i<<1);
00443 p_Img->spiral_qpel_search[k].mv_x = (short) -(l<<2);
00444 p_Img->spiral_qpel_search[k++].mv_y = (short) (i<<2);
00445 p_Img->spiral_search[k].mv_x = (short) l;
00446 p_Img->spiral_search[k].mv_y = (short) i;
00447 p_Img->spiral_hpel_search[k].mv_x = (short) (l<<1);
00448 p_Img->spiral_hpel_search[k].mv_y = (short) (i<<1);
00449 p_Img->spiral_qpel_search[k].mv_x = (short) (l<<2);
00450 p_Img->spiral_qpel_search[k++].mv_y = (short) (i<<2);
00451 }
00452 }
00453
00454
00455 p_Img->start_me_refinement_hp = (p_Inp->ChromaMEEnable == 1 || p_Inp->MEErrorMetric[F_PEL] != p_Inp->MEErrorMetric[H_PEL] ) ? 0 : 1;
00456 p_Img->start_me_refinement_qp = (p_Inp->ChromaMEEnable == 1 || p_Inp->MEErrorMetric[H_PEL] != p_Inp->MEErrorMetric[Q_PEL] ) ? 0 : 1;
00457
00458 select_distortion(p_Img, p_Inp);
00459
00460
00461 for (i=0; i<3; i++)
00462 {
00463 switch(p_Inp->MEErrorMetric[i])
00464 {
00465 case ERROR_SAD:
00466 p_Img->computeUniPred[i] = computeSAD;
00467 p_Img->computeUniPred[i + 3] = computeSADWP;
00468 p_Img->computeBiPred1[i] = computeBiPredSAD1;
00469 p_Img->computeBiPred2[i] = computeBiPredSAD2;
00470 break;
00471 case ERROR_SSE:
00472 p_Img->computeUniPred[i] = computeSSE;
00473 p_Img->computeUniPred[i + 3] = computeSSEWP;
00474 p_Img->computeBiPred1[i] = computeBiPredSSE1;
00475 p_Img->computeBiPred2[i] = computeBiPredSSE2;
00476 break;
00477 case ERROR_SATD :
00478 default:
00479 p_Img->computeUniPred[i] = computeSATD;
00480 p_Img->computeUniPred[i + 3] = computeSATDWP;
00481 p_Img->computeBiPred1[i] = computeBiPredSATD1;
00482 p_Img->computeBiPred2[i] = computeBiPredSATD2;
00483 break;
00484 }
00485 }
00486 if (!p_Inp->IntraProfile)
00487 {
00488 if(p_Inp->SearchMode == FAST_FULL_SEARCH)
00489 InitializeFastFullIntegerSearch (p_Img, p_Inp);
00490
00491 if (p_Inp->SearchMode == UM_HEX)
00492 UMHEX_DefineThreshold(p_Img);
00493 }
00494 }
00495
00496
00497
00498
00499
00500
00501
00502 void
00503 Clear_Motion_Search_Module (ImageParameters *p_Img, InputParameters *p_Inp)
00504 {
00505 int search_range = p_Inp->search_range;
00506 int number_of_subpel_positions = 4 * (2*search_range+3);
00507 int max_mv_bits = 3 + 2 * (int)ceil (log(number_of_subpel_positions + 1) / log(2) + 1e-10);
00508 int max_mvd = (1<<( max_mv_bits >>1) ) - 1;
00509
00510
00511
00512 p_Img->mvbits -= max_mvd;
00513 #if (JM_MEM_DISTORTION)
00514 p_Img->imgpel_abs -= p_Img->imgpel_abs_range / 2;
00515 p_Img->imgpel_quad -= p_Img->imgpel_abs_range / 2;
00516 #endif
00517
00518
00519 free (p_Img->spiral_search);
00520 free (p_Img->spiral_hpel_search);
00521 free (p_Img->spiral_qpel_search);
00522 free (p_Img->mvbits);
00523 free (p_Img->refbits);
00524
00525 #if (JM_MEM_DISTORTION)
00526 free (p_Img->imgpel_abs);
00527 free (p_Img->imgpel_quad);
00528 #endif
00529
00530 if (p_Img->motion_cost)
00531 free_mem4Dint (p_Img->motion_cost);
00532
00533 if ((p_Inp->SearchMode == FAST_FULL_SEARCH) && (!p_Inp->IntraProfile) )
00534 ClearFastFullIntegerSearch (p_Img);
00535 }
00536 static inline int mv_bits_cost(ImageParameters *p_Img, short ***all_mv, short ***p_mv, int by, int bx, int step_v0, int step_v, int step_h0, int step_h, int mvd_bits)
00537 {
00538 int v, h;
00539 for (v=by; v<by + step_v0; v+=step_v)
00540 {
00541 for (h=bx; h<bx + step_h0; h+=step_h)
00542 {
00543 mvd_bits += (int) p_Img->mvbits[ all_mv[v][h][0] - p_mv[v][h][0] ];
00544 mvd_bits += (int) p_Img->mvbits[ all_mv[v][h][1] - p_mv[v][h][1] ];
00545 }
00546 }
00547 return mvd_bits;
00548 }
00549
00550 static inline int mv_bit_cost(Macroblock *currMB, short ***all_mv, int cur_list, short cur_ref, int by, int bx, int step_v0, int step_v, int step_h0, int step_h, int mvd_bits)
00551 {
00552 int v, h;
00553 short predMV[2];
00554 PixelPos block[4];
00555 ImageParameters *p_Img = currMB->p_Img;
00556 PicMotionParams *motion = &p_Img->enc_picture->motion;
00557
00558 for (v=by; v<by + step_v0; v+=step_v)
00559 {
00560 for (h=bx; h<bx + step_h0; h+=step_h)
00561 {
00562
00563 get_neighbors(currMB, block, h, v, step_h);
00564
00565 currMB->GetMVPredictor (currMB, block, predMV, cur_ref, motion->ref_idx[cur_list], motion->mv[cur_list], h, v, step_h, step_v);
00566
00567 mvd_bits += p_Img->mvbits[ all_mv[v][h][0] - predMV[0] ];
00568 mvd_bits += p_Img->mvbits[ all_mv[v][h][1] - predMV[1] ];
00569 }
00570 }
00571
00572 return mvd_bits;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581 int BPredPartitionCost (Macroblock *currMB,
00582 int blocktype,
00583 int block8x8,
00584 short ref_l0,
00585 short ref_l1,
00586 int lambda_factor,
00587 int list)
00588 {
00589 ImageParameters *p_Img = currMB->p_Img;
00590 Slice *currSlice = currMB->p_slice;
00591 imgpel **cur_img = p_Img->pCurImg;
00592
00593 int curr_blk[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
00594 int bsx = (short) imin(block_size[blocktype][0], 8);
00595 int bsy = (short) imin(block_size[blocktype][1], 8);
00596
00597 short pic_pix_x, pic_pix_y;
00598 short v, h;
00599 int i, j, k;
00600 int mcost;
00601
00602 int mvd_bits = 0;
00603 int diff64[64];
00604
00605
00606 short parttype = (short) (blocktype < 4 ? blocktype : 4);
00607 short step_h0 = (part_size[ parttype][0]);
00608 short step_v0 = (part_size[ parttype][1]);
00609 short step_h = (part_size[blocktype][0]);
00610 short step_v = (part_size[blocktype][1]);
00611 int bxx, byy;
00612 short by0_part = by0[parttype][block8x8];
00613 short bx0_part = bx0[parttype][block8x8];
00614
00615 short ***all_mv_l0 = currSlice->bipred_mv[list][LIST_0][ref_l0][blocktype];
00616 short ***all_mv_l1 = currSlice->bipred_mv[list][LIST_1][ref_l1][blocktype];
00617 imgpel **mb_pred = currSlice->mb_pred[0];
00618
00619
00620 mvd_bits = mv_bit_cost(currMB, all_mv_l0, LIST_0, ref_l0, by0_part, bx0_part, step_v0, step_v, step_h0, step_h, mvd_bits);
00621
00622 mvd_bits = mv_bit_cost(currMB, all_mv_l1, LIST_1, ref_l1, by0_part, bx0_part, step_v0, step_v, step_h0, step_h, mvd_bits);
00623
00624 mcost = WEIGHTED_COST (lambda_factor, mvd_bits);
00625
00626
00627 if ((!currSlice->p_Inp->Transform8x8Mode) || (blocktype>4))
00628 {
00629 for (byy=0, v = by0_part << 2; v < (by0_part + step_v0) << 2; byy += 4, v += 4)
00630 {
00631
00632 pic_pix_y = currMB->opix_y + v;
00633 for (bxx=0, h = (bx0_part << 2); h < (bx0_part + step_h0) << 2; bxx += 4, h += 4)
00634 {
00635 pic_pix_x = currMB->pix_x + h;
00636 luma_prediction_bi (currMB, h, v, 4, 4, blocktype, blocktype, ref_l0, ref_l1, list);
00637
00638 for (k = j = 0; j < 4; j++)
00639 {
00640 for (i = 0; i < 4; i++)
00641 diff64[k++] = cur_img[pic_pix_y+j][pic_pix_x+i] - mb_pred[j + v][i + h];
00642 }
00643
00644 mcost += p_Img->distortion4x4 (diff64, INT_MAX);
00645 }
00646 }
00647 }
00648 else
00649 {
00650 for (byy=0, v = by0_part << 2; v < (by0_part + step_v0) << 2; byy += 4, v += 4)
00651 {
00652
00653 pic_pix_y = currMB->opix_y + v;
00654 for (bxx=0, h = (bx0_part << 2); h < (bx0_part + step_h0) << 2; bxx += 4, h += 4)
00655 {
00656 pic_pix_x = currMB->pix_x + h;
00657 luma_prediction_bi (currMB, h, v, 4, 4, blocktype, blocktype, ref_l0, ref_l1, list);
00658
00659 for (k = j = 0; j < 4; j++)
00660 {
00661 for (i = 0; i < 4; i++)
00662 curr_blk[byy+j][bxx+i] = cur_img[pic_pix_y+j][pic_pix_x+i] - mb_pred[j + v][i + h];
00663 }
00664 }
00665 }
00666
00667 for (byy=0; byy < block_size[parttype][1]; byy += bsy)
00668 {
00669 for (bxx=0; bxx < block_size[parttype][0]; bxx += bsx)
00670 {
00671 for (k=0, j = byy; j < byy + 8; j++, k += 8)
00672 memcpy(&diff64[k], &(curr_blk[j][bxx]), 8 * sizeof(int));
00673
00674 mcost += p_Img->distortion8x8(diff64, INT_MAX);
00675 }
00676 }
00677 }
00678 return mcost;
00679 }
00680
00681 void update_mv_block(Macroblock *currMB, MEBlock *mv_block, int h, int v)
00682 {
00683 mv_block->block_x = (short) h;
00684 mv_block->block_y = (short) v;
00685 mv_block->pos_x = (short) (currMB->pix_x + (h << 2));
00686 mv_block->pos_y = (short) (currMB->opix_y + (v << 2));
00687 mv_block->pos_x2 = (short) (mv_block->pos_x >> 2);
00688 mv_block->pos_y2 = (short) (mv_block->pos_y >> 2);
00689 #if (PAD_AFTER)
00690 mv_block->pos_x_padded = (short) (mv_block->pos_x << 2);
00691 mv_block->pos_y_padded = (short) (mv_block->pos_y << 2);
00692 #else
00693 mv_block->pos_x_padded = (short) (mv_block->pos_x << 2) + IMG_PAD_SIZE_TIMES4;
00694 mv_block->pos_y_padded = (short) (mv_block->pos_y << 2) + IMG_PAD_SIZE_TIMES4;
00695 #endif
00696 mv_block->pos_cr_x = (short) (mv_block->pos_x >> currMB->p_Img->shift_cr_x);
00697 mv_block->pos_cr_y = (short) (mv_block->pos_y >> currMB->p_Img->shift_cr_y);
00698 }
00699
00700
00701
00702
00703
00704
00705
00706 void init_mv_block(Macroblock *currMB, MEBlock *mv_block, short blocktype, int list, char ref_idx, short mb_x, short mb_y)
00707 {
00708 InputParameters *p_Inp = currMB->p_Inp;
00709 ImageParameters *p_Img = currMB->p_Img;
00710 Slice *currSlice = currMB->p_slice;
00711 mv_block->blocktype = blocktype;
00712 mv_block->blocksize_x = block_size[blocktype][0];
00713 mv_block->blocksize_y = block_size[blocktype][1];
00714
00715 update_mv_block(currMB, mv_block, mb_x, mb_y);
00716
00717 mv_block->list = (char) list;
00718 mv_block->ref_idx = ref_idx;
00719
00720 mv_block->mv[LIST_0].mv_x = 0;
00721 mv_block->mv[LIST_0].mv_y = 0;
00722 mv_block->mv[LIST_1].mv_x = 0;
00723 mv_block->mv[LIST_1].mv_y = 0;
00724
00725 mv_block->p_Img = p_Img;
00726 mv_block->p_slice = currSlice;
00727 mv_block->cost = INT_MAX;
00728 mv_block->search_pos2 = 9;
00729 mv_block->search_pos4 = 9;
00730
00731 if ((mv_block->orig_pic = (imgpel**)calloc(3, sizeof(imgpel *))) == NULL)
00732 no_mem_exit("init_mv_block: mv_block->orig_pic");
00733
00734 get_mem1Dpel(&(mv_block->orig_pic[0]), mv_block->blocksize_x * mv_block->blocksize_y);
00735
00736 mv_block->ChromaMEEnable = p_Inp->ChromaMEEnable;
00737
00738 mv_block->apply_bi_weights = p_Inp->UseWeightedReferenceME && ((currSlice->slice_type == B_SLICE) && p_Img->active_pps->weighted_bipred_idc != 0);
00739 mv_block->apply_weights = p_Inp->UseWeightedReferenceME && ( currSlice->weighted_prediction != 0 );
00740
00741 if (p_Inp->ChromaMEEnable)
00742 {
00743 mv_block->blocksize_cr_x = (short) (mv_block->blocksize_x >> p_Img->shift_cr_x);
00744 mv_block->blocksize_cr_y = (short) (mv_block->blocksize_y >> p_Img->shift_cr_y);
00745
00746 mv_block->ChromaMEWeight = p_Inp->ChromaMEWeight;
00747 get_mem1Dpel(&(mv_block->orig_pic[1]), mv_block->blocksize_cr_x * mv_block->blocksize_cr_y);
00748 get_mem1Dpel(&(mv_block->orig_pic[2]), mv_block->blocksize_cr_x * mv_block->blocksize_cr_y);
00749 }
00750
00751 if (mv_block->apply_weights)
00752 {
00753 mv_block->computePredFPel = p_Img->computeUniPred[F_PEL + 3];
00754 mv_block->computePredHPel = p_Img->computeUniPred[H_PEL + 3];
00755 mv_block->computePredQPel = p_Img->computeUniPred[Q_PEL + 3];
00756 mv_block->computeBiPredFPel = p_Img->computeBiPred2[F_PEL];
00757 mv_block->computeBiPredHPel = p_Img->computeBiPred2[H_PEL];
00758 mv_block->computeBiPredQPel = p_Img->computeBiPred2[Q_PEL];
00759 }
00760 else
00761 {
00762 mv_block->computePredFPel = p_Img->computeUniPred[F_PEL];
00763 mv_block->computePredHPel = p_Img->computeUniPred[H_PEL];
00764 mv_block->computePredQPel = p_Img->computeUniPred[Q_PEL];
00765 mv_block->computeBiPredFPel = p_Img->computeBiPred1[F_PEL];
00766 mv_block->computeBiPredHPel = p_Img->computeBiPred1[H_PEL];
00767 mv_block->computeBiPredQPel = p_Img->computeBiPred1[Q_PEL];
00768 }
00769 }
00770
00771
00772
00773
00774
00775
00776
00777 void free_mv_block(InputParameters *p_Inp, MEBlock *mv_block)
00778 {
00779 if (mv_block->orig_pic)
00780 {
00781 free_mem1Dpel(mv_block->orig_pic[0]);
00782 if (p_Inp->ChromaMEEnable)
00783 {
00784 free_mem1Dpel(mv_block->orig_pic[1]);
00785 free_mem1Dpel(mv_block->orig_pic[2]);
00786 }
00787 free(mv_block->orig_pic);
00788 }
00789 }
00790
00791
00792 void get_original_block(ImageParameters *p_Img, InputParameters *p_Inp, MEBlock *mv_block)
00793 {
00794
00795
00796
00797 imgpel *orig_pic_tmp = mv_block->orig_pic[0];
00798 int bsx = mv_block->blocksize_x;
00799 int pic_pix_x = mv_block->pos_x;
00800 int i, j;
00801 imgpel **cur_img = &p_Img->pCurImg[mv_block->pos_y];
00802
00803 for (j = 0; j < mv_block->blocksize_y; j++)
00804 {
00805 memcpy(orig_pic_tmp,&cur_img[j][pic_pix_x], bsx * sizeof(imgpel));
00806 orig_pic_tmp += bsx;
00807 }
00808
00809 if ( p_Inp->ChromaMEEnable )
00810 {
00811 bsx = mv_block->blocksize_cr_x;
00812 pic_pix_x = mv_block->pos_cr_x;
00813
00814
00815 for ( i = 1; i<=2; i++)
00816 {
00817 cur_img = &p_Img->pImgOrg[i][mv_block->pos_cr_y];
00818 orig_pic_tmp = mv_block->orig_pic[i];
00819 for (j = 0; j < mv_block->blocksize_cr_y; j++)
00820 {
00821 memcpy(orig_pic_tmp, &(cur_img[j][pic_pix_x]), bsx * sizeof(imgpel));
00822 orig_pic_tmp += bsx;
00823 }
00824 }
00825 }
00826 }
00827
00828
00829
00830
00831
00832
00833
00834 int
00835 BlockMotionSearch (Macroblock *currMB,
00836 MEBlock *mv_block,
00837 int mb_x,
00838 int mb_y,
00839 int* lambda_factor)
00840 {
00841
00842
00843 Slice *currSlice = currMB->p_slice;
00844 ImageParameters *p_Img = currMB->p_Img;
00845 InputParameters *p_Inp = currMB->p_Inp;
00846
00847 short pred_mv[2];
00848 int i, j;
00849
00850 int max_value = INT_MAX;
00851 int min_mcost = max_value;
00852
00853 int block_x = (mb_x>>2);
00854 int block_y = (mb_y>>2);
00855
00856 int bsx = mv_block->blocksize_x;
00857 int bsy = mv_block->blocksize_y;
00858
00859 short pic_pix_x = (short) (currMB->pix_x + mb_x);
00860
00861 int blocktype = mv_block->blocktype;
00862 int list = mv_block->list;
00863 short ref = mv_block->ref_idx;
00864 MotionVector *mv = &mv_block->mv[list], pred;
00865
00866 short*** all_mv = &currSlice->all_mv[list][ref][blocktype][block_y];
00867 PicMotionParams *motion = &p_Img->enc_picture->motion;
00868
00869 int *prevSad = (p_Inp->SearchMode == EPZS)? currSlice->p_EPZS->distortion[list + currMB->list_offset][blocktype - 1]: NULL;
00870
00871 get_neighbors(currMB, mv_block->block, mb_x, mb_y, bsx);
00872
00873 PrepareMEParams(currSlice, mv_block, p_Inp->ChromaMEEnable, list + currMB->list_offset, ref);
00874
00875
00876
00877
00878 if (blocktype > 4)
00879 get_original_block(p_Img, p_Inp, mv_block);
00880
00881
00882
00883
00884 if (p_Inp->SearchMode == UM_HEX)
00885 {
00886 p_Img->p_UMHex->UMHEX_blocktype = blocktype;
00887 p_Img->p_UMHex->bipred_flag = 0;
00888 UMHEXSetMotionVectorPredictor(currMB, pred_mv, motion->ref_idx[list], motion->mv[list], ref, list, mb_x, mb_y, bsx, bsy, mv_block);
00889 }
00890 else if (p_Inp->SearchMode == UM_HEX_SIMPLE)
00891 {
00892 smpUMHEX_setup(currMB, ref, list, block_y, block_x, blocktype, currSlice->all_mv );
00893 currMB->GetMVPredictor (currMB, mv_block->block, pred_mv, ref, motion->ref_idx[list], motion->mv[list], mb_x, mb_y, bsx, bsy);
00894 }
00895 else
00896 {
00897 currMB->GetMVPredictor (currMB, mv_block->block, pred_mv, ref, motion->ref_idx[list], motion->mv[list], mb_x, mb_y, bsx, bsy);
00898 }
00899
00900 pred.mv_x = pred_mv[0];
00901 pred.mv_y = pred_mv[1];
00902
00903
00904
00905
00906 if (p_Inp->EPZSSubPelGrid)
00907 {
00908 *mv = pred;
00909 }
00910 else
00911 {
00912 #if (JM_INT_DIVIDE)
00913 mv->mv_x = (short) (((pred.mv_x + 2) >> 2) * 4);
00914 mv->mv_y = (short) (((pred.mv_y + 2) >> 2) * 4);
00915 #else
00916 mv->mv_x = (short) ((pred.mv_x / 4) * 4);
00917 mv->mv_y = (short) ((pred.mv_y / 4) * 4);
00918 #endif
00919 }
00920
00921 if (!p_Inp->rdopt)
00922 {
00923
00924 mv->mv_x = (short) iClip3 (mv_block->searchRange.min_x, mv_block->searchRange.max_x, mv->mv_x);
00925 mv->mv_y = (short) iClip3 (mv_block->searchRange.min_y, mv_block->searchRange.max_y, mv->mv_y);
00926 }
00927
00928
00929 clip_mv_range(p_Img, 0, mv, Q_PEL);
00930
00931
00932 min_mcost = currMB->IntPelME (currMB, &pred, mv_block, min_mcost, lambda_factor[F_PEL]);
00933
00934
00935
00936
00937
00938 mv_block->ChromaMEEnable = (p_Inp->ChromaMEEnable == ME_YUV_FP_SP ) ? 1 : 0;
00939
00940 if (!p_Inp->DisableSubpelME)
00941 {
00942 if (p_Inp->SearchMode != EPZS || (ref == 0 || currSlice->structure != FRAME || (ref > 0 && min_mcost < 3.5 * prevSad[pic_pix_x >> 2])))
00943 {
00944 if ( !p_Img->start_me_refinement_hp )
00945 {
00946 min_mcost = max_value;
00947 }
00948 min_mcost = currMB->SubPelME (currMB, &pred, mv_block, min_mcost, lambda_factor);
00949 }
00950 }
00951
00952
00953
00954 clip_mv_range(p_Img, 0, mv, Q_PEL);
00955
00956 if (!p_Inp->rdopt)
00957 {
00958
00959 if (blocktype == 1 && (currSlice->slice_type == P_SLICE||currSlice->slice_type == SP_SLICE))
00960 {
00961 int cost;
00962
00963 FindSkipModeMotionVector (currMB);
00964
00965 cost = GetSkipCostMB (currMB);
00966 cost -= ((lambda_factor[Q_PEL] + 4096) >> 13);
00967 if (cost < min_mcost)
00968 {
00969 min_mcost = cost;
00970 mv->mv_x = currSlice->all_mv [0][0][0][0][0][0];
00971 mv->mv_y = currSlice->all_mv [0][0][0][0][0][1];
00972 }
00973 }
00974 }
00975
00976
00977
00978
00979
00980
00981 for (i=block_x; i < block_x + (bsx>>2); i++)
00982 {
00983 all_mv[0][i][0] = mv->mv_x;
00984 all_mv[0][i][1] = mv->mv_y;
00985 }
00986
00987
00988 for (j=1; j < (bsy>>2); j++)
00989 {
00990 memcpy(all_mv[j][block_x], all_mv[0][block_x], (bsx>>2) * 2 * sizeof(short));
00991 }
00992
00993
00994 if (currSlice->slice_type == B_SLICE && is_bipred_enabled(p_Inp, blocktype) && (ref == 0))
00995 {
00996 BiPredBlockMotionSearch(currMB, mv_block, &pred, mb_x, mb_y, lambda_factor);
00997 }
00998
00999 return min_mcost;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009 static int BiPredBlockMotionSearch(Macroblock *currMB,
01010 MEBlock *mv_block,
01011 MotionVector *pred_mv,
01012 int mb_x,
01013 int mb_y,
01014 int *lambda_factor)
01015 {
01016 ImageParameters *p_Img = currMB->p_Img;
01017 InputParameters *p_Inp = currMB->p_Inp;
01018 Slice *currSlice = currMB->p_slice;
01019 int list = mv_block->list;
01020 int i, j;
01021 short bipred_type = list ? 0 : 1;
01022 short****** bipred_mv = currSlice->bipred_mv[bipred_type];
01023 int min_mcostbi = INT_MAX;
01024 MotionVector *mv = &mv_block->mv[list];
01025 MotionVector bimv, tempmv;
01026 MotionVector pred_mv1, pred_mv2, pred_bi;
01027 MotionVector bi_mv1 = { 0, 0}, bi_mv2 = { 0, 0};
01028 short iterlist = (short) list;
01029 short pred_mv_bi[2];
01030 int block_x = (mb_x>>2);
01031 int block_y = (mb_y>>2);
01032 int blocktype = mv_block->blocktype;
01033 int bsx = mv_block->blocksize_x;
01034 int bsy = mv_block->blocksize_y;
01035
01036 PicMotionParams *motion = &p_Img->enc_picture->motion;
01037
01038
01039
01040 if (p_Inp->SearchMode == UM_HEX)
01041 {
01042 p_Img->p_UMHex->bipred_flag = 1;
01043 UMHEXSetMotionVectorPredictor(currMB, pred_mv_bi, motion->ref_idx[list ^ 1], motion->mv[list ^ 1], 0, list ^ 1, mb_x, mb_y, bsx, bsy, mv_block);
01044 }
01045 else
01046 currMB->GetMVPredictor (currMB, mv_block->block, pred_mv_bi, 0, motion->ref_idx[list ^ 1], motion->mv[list ^ 1], mb_x, mb_y, bsx, bsy);
01047
01048 pred_bi.mv_x = pred_mv_bi[0];
01049 pred_bi.mv_y = pred_mv_bi[1];
01050
01051 if ((p_Inp->SearchMode != EPZS) || (p_Inp->EPZSSubPelGrid == 0))
01052 {
01053 mv->mv_x = ((mv->mv_x + 2) >> 2) * 4;
01054 mv->mv_y = ((mv->mv_y + 2) >> 2) * 4;
01055 bimv.mv_x = ((pred_bi.mv_x + 2) >> 2) * 4;
01056 bimv.mv_y = ((pred_bi.mv_y + 2) >> 2) * 4;
01057 }
01058 else
01059 {
01060 bimv = pred_bi;
01061 }
01062
01063
01064 for (mv_block->iteration_no = 0; mv_block->iteration_no <= p_Inp->BiPredMERefinements; mv_block->iteration_no++)
01065 {
01066 if (mv_block->iteration_no & 0x01)
01067 {
01068 pred_mv1 = *pred_mv;
01069 pred_mv2 = pred_bi;
01070 bi_mv1 = *mv;
01071 bi_mv2 = bimv;
01072 iterlist = (short) list;
01073 }
01074 else
01075 {
01076 pred_mv1 = pred_bi;
01077 pred_mv2 = *pred_mv;
01078 bi_mv1 = bimv;
01079 bi_mv2 = *mv;
01080 iterlist = (short) (list ^ 1);
01081 }
01082
01083 tempmv = bi_mv1;
01084
01085 PrepareBiPredMEParams(currSlice, mv_block, mv_block->ChromaMEEnable, iterlist, currMB->list_offset, mv_block->ref_idx);
01086
01087 min_mcostbi = currMB->BiPredME (currMB, iterlist,
01088 &pred_mv1, &pred_mv2, &bi_mv1, &bi_mv2, mv_block,
01089 (p_Inp->BiPredMESearchRange <<2)>>mv_block->iteration_no, min_mcostbi, lambda_factor[F_PEL]);
01090
01091 if (mv_block->iteration_no > 0 && (tempmv.mv_x == bi_mv1.mv_x) && (tempmv.mv_y == bi_mv1.mv_y))
01092 {
01093 break;
01094 }
01095 }
01096
01097 if (!p_Inp->DisableSubpelME)
01098 {
01099 if (p_Inp->BiPredMESubPel)
01100 {
01101 min_mcostbi = INT_MAX;
01102 PrepareBiPredMEParams(currSlice, mv_block, mv_block->ChromaMEEnable, iterlist, currMB->list_offset, mv_block->ref_idx);
01103
01104 min_mcostbi = currMB->SubPelBiPredME (currMB, mv_block, iterlist, &pred_mv1, &pred_mv2, &bi_mv1, &bi_mv2, min_mcostbi, lambda_factor);
01105 }
01106
01107 if (p_Inp->BiPredMESubPel==2)
01108 {
01109 min_mcostbi = INT_MAX;
01110 PrepareBiPredMEParams(currSlice, mv_block, mv_block->ChromaMEEnable, iterlist ^ 1, currMB->list_offset, mv_block->ref_idx);
01111
01112 min_mcostbi = currMB->SubPelBiPredME (currMB, mv_block, iterlist ^ 1, &pred_mv2, &pred_mv1, &bi_mv2, &bi_mv1, min_mcostbi, lambda_factor);
01113 }
01114 }
01115
01116 clip_mv_range(p_Img, 0, &bi_mv1, Q_PEL);
01117 clip_mv_range(p_Img, 0, &bi_mv2, Q_PEL);
01118
01119 for (j=block_y; j < block_y + (bsy>>2); j++)
01120 {
01121 for (i=block_x ; i < block_x + (bsx>>2); i++)
01122 {
01123 bipred_mv[iterlist ][(short) mv_block->ref_idx][blocktype][j][i][0] = bi_mv1.mv_x;
01124 bipred_mv[iterlist ][(short) mv_block->ref_idx][blocktype][j][i][1] = bi_mv1.mv_y;
01125 bipred_mv[iterlist ^ 1][(short) mv_block->ref_idx][blocktype][j][i][0] = bi_mv2.mv_x;
01126 bipred_mv[iterlist ^ 1][(short) mv_block->ref_idx][blocktype][j][i][1] = bi_mv2.mv_y;
01127 }
01128 }
01129 return min_mcostbi;
01130 }
01131
01132
01133
01134
01135
01136
01137
01138 int BIDPartitionCost (Macroblock *currMB,
01139 int blocktype,
01140 int block8x8,
01141 char cur_ref[2],
01142 int lambda_factor)
01143 {
01144 ImageParameters *p_Img = currMB->p_Img;
01145 Slice *currSlice = currMB->p_slice;
01146 imgpel **cur_img = p_Img->pCurImg;
01147
01148 int curr_blk[MB_BLOCK_SIZE][MB_BLOCK_SIZE];
01149 int bsx = imin(block_size[blocktype][0],8);
01150 int bsy = imin(block_size[blocktype][1],8);
01151
01152 short pic_pix_x, pic_pix_y, block_x, block_y;
01153 int v, h, mcost, i, j, k;
01154 int mvd_bits = 0;
01155 int parttype = (blocktype < 4 ? blocktype : 4);
01156 int step_h0 = (part_size[ parttype][0]);
01157 int step_v0 = (part_size[ parttype][1]);
01158 int step_h = (part_size[blocktype][0]);
01159 int step_v = (part_size[blocktype][1]);
01160 int bxx, byy;
01161 int bx = bx0[parttype][block8x8];
01162 int by = by0[parttype][block8x8];
01163 short *** all_mv_l0 = currSlice->all_mv [LIST_0][(int) cur_ref[LIST_0]][blocktype];
01164 short *** all_mv_l1 = currSlice->all_mv [LIST_1][(int) cur_ref[LIST_1]][blocktype];
01165 short bipred_me = 0;
01166 imgpel **mb_pred = currSlice->mb_pred[0];
01167 int diff64[64];
01168
01169 int list_mode[2];
01170 list_mode[0] = blocktype;
01171 list_mode[1] = blocktype;
01172
01173
01174
01175
01176
01177 mvd_bits = mv_bit_cost(currMB, all_mv_l0, LIST_0, cur_ref[LIST_0], by, bx, step_v0, step_v, step_h0, step_h, mvd_bits);
01178
01179
01180 mvd_bits = mv_bit_cost(currMB, all_mv_l1, LIST_1, cur_ref[LIST_1], by, bx, step_v0, step_v, step_h0, step_h, mvd_bits);
01181
01182 mcost = WEIGHTED_COST (lambda_factor, mvd_bits);
01183
01184
01185 if ((!currSlice->p_Inp->Transform8x8Mode) || (blocktype>4))
01186 {
01187 for (byy=0, v=by; v<by + step_v0; byy+=4, v++)
01188 {
01189 pic_pix_y = (short) (currMB->opix_y + (block_y = (short) (v<<2)));
01190 for (bxx=0, h=bx; h<bx + step_h0; bxx+=4, h++)
01191 {
01192 pic_pix_x = (short) (currMB->pix_x + (block_x = (short) (h<<2)));
01193 luma_prediction (currMB, block_x, block_y, 4, 4, 2, list_mode, cur_ref, bipred_me);
01194
01195 for (k=j=0; j<4; j++)
01196 {
01197 for ( i=0; i<4; i++)
01198 diff64[k++] = curr_blk[byy+j][bxx+i] =
01199 cur_img[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
01200 }
01201
01202 mcost += p_Img->distortion4x4 (diff64, INT_MAX);
01203 }
01204 }
01205 }
01206 else
01207 {
01208 for (byy=0, v= (by << 2); v < (by + step_v0) << 2; byy += 4, v += 4)
01209 {
01210 pic_pix_y = (short) (currMB->opix_y + v);
01211 for (bxx=0, h = (bx << 2); h < (bx + step_h0) << 2; bxx+=4, h += 4)
01212 {
01213 pic_pix_x = (short) (currMB->pix_x + h);
01214 luma_prediction (currMB, h, v, 4, 4, 2, list_mode, cur_ref, bipred_me);
01215
01216 for (k=j=0; j<4; j++)
01217 {
01218 for ( i=0; i<4; i++)
01219 diff64[k++] = curr_blk[byy+j][bxx+i] =
01220 cur_img[pic_pix_y+j][pic_pix_x+i] - mb_pred[j + v][i + h];
01221 }
01222 }
01223 }
01224
01225 for (byy=0; byy < block_size[parttype][1]; byy+=bsy)
01226 {
01227 for (bxx=0; bxx<block_size[parttype][0]; bxx+=bsx)
01228 {
01229 for (k=0, j=byy;j<byy + 8;j++, k += 8)
01230 memcpy(&diff64[k], &(curr_blk[j][bxx]), 8 * sizeof(int));
01231
01232 mcost += p_Img->distortion8x8(diff64, INT_MAX);
01233 }
01234 }
01235 }
01236 return mcost;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245 static int GetSkipCostMB (Macroblock *currMB)
01246 {
01247 Slice *currSlice = currMB->p_slice;
01248 ImageParameters *p_Img = currMB->p_Img;
01249 InputParameters *p_Inp = currMB->p_Inp;
01250 int block_y, block_x, pic_pix_y, pic_pix_x, i, j, k;
01251 int cost = 0;
01252
01253 int curr_diff[8][8];
01254 int mb_x, mb_y;
01255 int block;
01256 imgpel **mb_pred = currSlice->mb_pred[0];
01257 char cur_ref[2] = {0, 0};
01258 int list_mode[2] = {0, 0};
01259 int diff [16];
01260 int diff64[64];
01261
01262 for(block = 0;block < 4;block++)
01263 {
01264 mb_y = (block >> 1)<<3;
01265 mb_x = (block & 0x01)<<3;
01266 for (block_y = mb_y; block_y < mb_y+8; block_y += 4)
01267 {
01268 pic_pix_y = currMB->opix_y + block_y;
01269 for (block_x = mb_x; block_x < mb_x + 8; block_x += 4)
01270 {
01271 pic_pix_x = currMB->pix_x + block_x;
01272
01273
01274 luma_prediction (currMB, block_x, block_y, 4, 4, 0, list_mode, cur_ref, 0);
01275
01276
01277 for (k = j = 0; j < 4; j++)
01278 {
01279 for (i = 0; i < 4; i++, k++)
01280 {
01281 diff[k] = curr_diff[block_y-mb_y+j][block_x-mb_x+i] = p_Img->pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
01282 }
01283 }
01284
01285 if(!((p_Inp->rdopt == 0) && (p_Inp->Transform8x8Mode)))
01286 cost += p_Img->distortion4x4 (diff, INT_MAX);
01287 }
01288 }
01289
01290 if((p_Inp->rdopt == 0) && (p_Inp->Transform8x8Mode))
01291 {
01292 for(k=j=0; j<8; j++, k+=8)
01293 memcpy(&diff64[k], &(curr_diff[j]), 8 * sizeof(int));
01294 cost += p_Img->distortion8x8 (diff64, INT_MAX);
01295 }
01296 }
01297
01298 return cost;
01299 }
01300
01301
01302
01303
01304
01305
01306
01307 void FindSkipModeMotionVector (Macroblock *currMB)
01308 {
01309 Slice *currSlice = currMB->p_slice;
01310 ImageParameters *p_Img = currMB->p_Img;
01311 PicMotionParams *motion = &p_Img->enc_picture->motion;
01312 int bx, by;
01313 short ***all_mv = currSlice->all_mv[0][0][0];
01314
01315 short pmv[2];
01316
01317 int zeroMotionAbove;
01318 int zeroMotionLeft;
01319 PixelPos mb[4];
01320 int a_mv_y = 0;
01321 int a_ref_idx = 0;
01322 int b_mv_y = 0;
01323 int b_ref_idx = 0;
01324 short ***mv = motion->mv[LIST_0];
01325
01326 get_neighbors(currMB, mb, 0, 0, 16);
01327
01328 if (mb[0].available)
01329 {
01330 a_mv_y = mv[mb[0].pos_y][mb[0].pos_x][1];
01331 a_ref_idx = motion->ref_idx[LIST_0][mb[0].pos_y][mb[0].pos_x];
01332
01333 if (currMB->mb_field && !p_Img->mb_data[mb[0].mb_addr].mb_field)
01334 {
01335 a_mv_y /=2;
01336 a_ref_idx *=2;
01337 }
01338 if (!currMB->mb_field && p_Img->mb_data[mb[0].mb_addr].mb_field)
01339 {
01340 a_mv_y *= 2;
01341 a_ref_idx >>=1;
01342 }
01343 }
01344
01345 if (mb[1].available)
01346 {
01347 b_mv_y = mv[mb[1].pos_y][mb[1].pos_x][1];
01348 b_ref_idx = motion->ref_idx[LIST_0][mb[1].pos_y][mb[1].pos_x];
01349
01350 if (currMB->mb_field && !p_Img->mb_data[mb[1].mb_addr].mb_field)
01351 {
01352 b_mv_y /=2;
01353 b_ref_idx *=2;
01354 }
01355 if (!currMB->mb_field && p_Img->mb_data[mb[1].mb_addr].mb_field)
01356 {
01357 b_mv_y *=2;
01358 b_ref_idx >>=1;
01359 }
01360 }
01361
01362 zeroMotionLeft = !mb[0].available ? 1 : a_ref_idx==0 && mv[mb[0].pos_y][mb[0].pos_x][0]==0 && a_mv_y==0 ? 1 : 0;
01363 zeroMotionAbove = !mb[1].available ? 1 : b_ref_idx==0 && mv[mb[1].pos_y][mb[1].pos_x][0]==0 && b_mv_y==0 ? 1 : 0;
01364
01365 if (zeroMotionAbove || zeroMotionLeft)
01366 {
01367 memset(all_mv [0][0], 0, 32 * sizeof(short));
01368 }
01369 else
01370 {
01371 currMB->GetMVPredictor (currMB, mb, pmv, 0, motion->ref_idx[LIST_0], mv, 0, 0, 16, 16);
01372
01373 for (bx = 0;bx < 4;bx++)
01374 {
01375 memcpy(all_mv [0][bx], pmv, 2* sizeof(short));
01376 }
01377
01378 for (by = 1;by < 4;by++)
01379 memcpy(all_mv [by][0], all_mv [0][0], 4 * 2* sizeof(short));
01380 }
01381 }
01382
01383
01384
01385
01386
01387
01388
01389 int GetDirectCost8x8 (Macroblock *currMB, int block, int *cost8x8)
01390 {
01391 Slice *currSlice = currMB->p_slice;
01392 ImageParameters *p_Img = currMB->p_Img;
01393 InputParameters *p_Inp = currMB->p_Inp;
01394 int block_y, block_x, pic_pix_y, pic_pix_x, i, j, k;
01395 int curr_diff[8][8];
01396 int cost = 0;
01397 int mb_y = (block >> 1)<<3;
01398 int mb_x = (block & 0x01)<<3;
01399 short bipred_me = 0;
01400 imgpel **mb_pred = currSlice->mb_pred[0];
01401 int list_mode[2] = {0, 0};
01402 int diff [16];
01403 int diff64[64];
01404
01405
01406 for (block_y=mb_y; block_y < mb_y + 8; block_y += 4)
01407 {
01408 pic_pix_y = currMB->opix_y + block_y;
01409
01410 for (block_x=mb_x; block_x<mb_x+8; block_x+=4)
01411 {
01412 pic_pix_x = currMB->pix_x + block_x;
01413
01414 if (currSlice->direct_pdir[pic_pix_y>>2][pic_pix_x>>2]<0)
01415 {
01416 *cost8x8=INT_MAX;
01417 return INT_MAX;
01418 }
01419
01420
01421
01422 luma_prediction (currMB, block_x, block_y, 4, 4,
01423 currSlice->direct_pdir[pic_pix_y>>2][pic_pix_x>>2], list_mode,
01424 currSlice->direct_ref_idx[pic_pix_y>>2][pic_pix_x>>2], bipred_me);
01425
01426
01427 for (k=j=0; j<4; j++)
01428 for (i=0; i<4; i++, k++)
01429 {
01430 diff[k] = curr_diff[block_y-mb_y+j][block_x - mb_x+i] =
01431 p_Img->pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
01432 }
01433
01434 cost += p_Img->distortion4x4 (diff, INT_MAX);
01435 }
01436 }
01437
01438 if((p_Inp->rdopt == 0) && (p_Inp->Transform8x8Mode))
01439 {
01440 k=0;
01441 for(j=0; j<8; j++, k+=8)
01442 memcpy(&diff64[k], &(curr_diff[j]), 8 * sizeof(int));
01443
01444 *cost8x8 += p_Img->distortion8x8 (diff64, INT_MAX);
01445 }
01446
01447 return cost;
01448 }
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458 int GetDirectCostMB (Macroblock *currMB)
01459 {
01460 Slice *currSlice = currMB->p_slice;
01461 InputParameters *p_Inp = currSlice->p_Inp;
01462 int i;
01463 int cost = 0;
01464 int cost8x8 = 0;
01465 int bslice = currSlice->slice_type == B_SLICE;
01466
01467 for (i=0; i<4; i++)
01468 {
01469 cost += GetDirectCost8x8 (currMB, i, &cost8x8);
01470 if (cost8x8 == INT_MAX) return INT_MAX;
01471 }
01472
01473 switch(p_Inp->Transform8x8Mode)
01474 {
01475 case 1:
01476 if((cost8x8 < cost)||
01477 !(p_Inp->InterSearch[bslice][5] &&
01478 p_Inp->InterSearch[bslice][6] &&
01479 p_Inp->InterSearch[bslice][7])
01480 )
01481 {
01482 cost = cost8x8;
01483 }
01484 break;
01485 case 2:
01486 cost = cost8x8;
01487 break;
01488 default:
01489 break;
01490 }
01491
01492 return cost;
01493 }
01494
01495
01496
01497
01498
01499
01500
01501
01502 void PartitionMotionSearch (Macroblock *currMB,
01503 int blocktype,
01504 int block8x8,
01505 int *lambda_factor)
01506 {
01507 ImageParameters *p_Img = currMB->p_Img;
01508 InputParameters *p_Inp = currMB->p_Inp;
01509 Slice *currSlice = currMB->p_slice;
01510 PicMotionParams *motion = &p_Img->enc_picture->motion;
01511
01512 char **ref_array;
01513 short ***mv_array;
01514 short ref = 0;
01515 int step_h = (part_size[blocktype][0]);
01516 int step_v = (part_size[blocktype][1]);
01517 int list = LIST_0;
01518 int numlists = (currSlice->slice_type == B_SLICE) ? 2 : 1;
01519 int list_offset = currMB->list_offset;
01520 int *m_cost;
01521 short by = by0[blocktype][block8x8];
01522 short bx = bx0[blocktype][block8x8];
01523 short pic_block_y = currMB->block_y + by;
01524 short pic_block_x = currMB->block_x + bx;
01525 MEBlock mv_block;
01526
01527 #if GET_METIME
01528 TIME_T me_time_start;
01529 TIME_T me_time_end;
01530 int64 me_tmp_time;
01531 gettime( &me_time_start );
01532 #endif
01533
01534 if (p_Img->Motion_Selected == 1)
01535 {
01536
01537 for (list=0; list<numlists;list++)
01538 {
01539
01540 ref_array = &motion->ref_idx[list][pic_block_y];
01541 mv_array = &motion->mv [list][pic_block_y];
01542
01543 for (ref=0; ref < p_Img->listXsize[list+list_offset]; ref++)
01544 {
01545 m_cost = &p_Img->motion_cost[blocktype][list][ref][block8x8];
01546
01547
01548 updateMV_mp(currMB, m_cost, ref, list, bx, by, blocktype, block8x8);
01549 set_me_parameters(ref_array, mv_array, currSlice->all_mv[list][ref][blocktype][by][bx], ref, step_h, step_v, pic_block_x);
01550 }
01551 }
01552 }
01553 else
01554 {
01555
01556 mv_block.test8x8 = p_Inp->Transform8x8Mode;
01557
01558 init_mv_block(currMB, &mv_block, (short) blocktype, list, (char) ref, bx, by);
01559
01560 if (p_Inp->SearchMode == EPZS)
01561 {
01562 if (p_Inp->EPZSSubPelGrid)
01563 currMB->IntPelME = EPZSIntPelBlockMotionSearch;
01564 else
01565 currMB->IntPelME = EPZSPelBlockMotionSearch;
01566 }
01567
01568 get_original_block(p_Img, p_Inp, &mv_block);
01569
01570
01571 {
01572
01573 for (list = 0; list < numlists; list++)
01574 {
01575
01576 ref_array = &motion->ref_idx[list][pic_block_y];
01577 mv_array = &motion->mv [list][pic_block_y];
01578 mv_block.list = (char) list;
01579
01580 for (ref=0; ref < p_Img->listXsize[list+list_offset]; ref++)
01581 {
01582 mv_block.ref_idx = (char) ref;
01583 m_cost = &p_Img->motion_cost[blocktype][list][ref][block8x8];
01584
01585
01586 get_search_range(&mv_block, p_Inp, ref, blocktype);
01587
01588
01589 *m_cost = BlockMotionSearch (currMB, &mv_block, bx<<2, by<<2, lambda_factor);
01590
01591 set_me_parameters(ref_array, mv_array, currSlice->all_mv[list][ref][blocktype][by][bx], ref, step_h, step_v, pic_block_x);
01592 }
01593 }
01594 }
01595
01596 free_mv_block(p_Inp, &mv_block);
01597 }
01598
01599 #if GET_METIME
01600 gettime(&me_time_end);
01601 me_tmp_time = timediff (&me_time_start, &me_time_end);
01602 p_Img->me_tot_time += me_tmp_time;
01603 p_Img->me_time += me_tmp_time;
01604 #endif
01605 }
01606
01607
01608
01609
01610
01611
01612
01613 void SubPartitionMotionSearch (Macroblock *currMB,
01614 int blocktype,
01615 int block8x8,
01616 int *lambda_factor)
01617 {
01618 Slice *currSlice = currMB->p_slice;
01619 ImageParameters *p_Img = currSlice->p_Img;
01620 InputParameters *p_Inp = currSlice->p_Inp;
01621 PicMotionParams *motion = &p_Img->enc_picture->motion;
01622
01623 char **ref_array;
01624 short ***mv_array;
01625 short *all_mv;
01626 short ref = 0;
01627 int v, h;
01628 int mcost;
01629 int pic_block_y;
01630 int parttype = 4;
01631 short step_h0 = (part_size[ parttype][0]);
01632 short step_v0 = (part_size[ parttype][1]);
01633 short step_h = (part_size[blocktype][0]);
01634 short step_v = (part_size[blocktype][1]);
01635 short list = LIST_0;
01636 int numlists = (currSlice->slice_type == B_SLICE) ? 2 : 1;
01637 int list_offset = currMB->list_offset;
01638 int *m_cost;
01639 short by = by0[parttype][block8x8];
01640 short bx = bx0[parttype][block8x8];
01641 MEBlock mv_block;
01642
01643 #if GET_METIME
01644 TIME_T me_time_start;
01645 TIME_T me_time_end;
01646 int64 me_tmp_time;
01647 gettime( &me_time_start );
01648 #endif
01649
01650 if (p_Img->Motion_Selected == 1)
01651 {
01652
01653 for (list=0; list<numlists;list++)
01654 {
01655 ref_array = motion->ref_idx[list];
01656 mv_array = motion->mv[list];
01657 for (ref=0; ref < p_Img->listXsize[list+list_offset]; ref++)
01658 {
01659 m_cost = &p_Img->motion_cost[blocktype][list][ref][block8x8];
01660
01661
01662 for (v=by; v<by + step_v0; v += step_v)
01663 {
01664 pic_block_y = currMB->block_y + v;
01665 for (h=bx; h<bx+step_h0; h+=step_h)
01666 {
01667 all_mv = currSlice->all_mv[list][ref][blocktype][v][h];
01668
01669 updateMV_mp(currMB, m_cost, ref, list, h, v, blocktype, block8x8);
01670
01671
01672 set_me_parameters(&ref_array [pic_block_y], &mv_array [pic_block_y], all_mv, ref, step_h, step_v, currMB->block_x + h);
01673 }
01674 }
01675 }
01676 }
01677 }
01678 else
01679 {
01680
01681 mv_block.test8x8 = p_Inp->Transform8x8Mode && blocktype == 4;
01682
01683 if (p_Inp->SearchMode == EPZS)
01684 {
01685 if (p_Inp->EPZSSubPelGrid)
01686 {
01687 if (blocktype > 4)
01688 currMB->IntPelME = EPZSIntPelBlockMotionSearchSubMB;
01689 else
01690 currMB->IntPelME = EPZSIntPelBlockMotionSearch;
01691 }
01692 else
01693 {
01694 if (blocktype > 4)
01695 currMB->IntPelME = EPZSPelBlockMotionSearchSubMB;
01696 else
01697 currMB->IntPelME = EPZSPelBlockMotionSearch;
01698 }
01699 }
01700
01701 init_mv_block(currMB, &mv_block, (short) blocktype, list, (char) ref, bx, by);
01702 if (blocktype == 4)
01703 get_original_block(p_Img, p_Inp, &mv_block);
01704
01705
01706 for (list=0; list<numlists;list++)
01707 {
01708 mv_block.list = (char) list;
01709
01710 ref_array = motion->ref_idx[list];
01711 mv_array = motion->mv[list];
01712
01713 for (ref=0; ref < p_Img->listXsize[list+list_offset]; ref++)
01714 {
01715 mv_block.ref_idx = (char) ref;
01716 m_cost = &p_Img->motion_cost[blocktype][list][ref][block8x8];
01717
01718 get_search_range(&mv_block, p_Inp, ref, blocktype);
01719
01720
01721 *m_cost = 0;
01722
01723
01724 for (v=by; v<by + step_v0; v += step_v)
01725 {
01726 pic_block_y = currMB->block_y + v;
01727
01728 for (h=bx; h<bx+step_h0; h+=step_h)
01729 {
01730 all_mv = currSlice->all_mv[list][ref][blocktype][v][h];
01731
01732
01733 {
01734 update_mv_block(currMB, &mv_block, h, v);
01735
01736 get_search_range(&mv_block, p_Inp, ref, blocktype);
01737
01738 mcost = BlockMotionSearch (currMB, &mv_block, h<<2, v<<2, lambda_factor);
01739
01740 *m_cost += mcost;
01741
01742 }
01743
01744
01745 set_me_parameters(&ref_array [pic_block_y], &mv_array [pic_block_y], all_mv, ref, step_h, step_v, currMB->block_x + h);
01746 }
01747 }
01748
01749 if ( (p_Inp->Transform8x8Mode == 1) && p_Inp->RDOQ_CP_MV && (blocktype == 4) && currMB->luma_transform_size_8x8_flag)
01750 {
01751 currSlice->tmp_mv8[list][ref][by][bx].mv_x = currSlice->all_mv[list][ref][blocktype][by][bx][0];
01752 currSlice->tmp_mv8[list][ref][by][bx].mv_y = currSlice->all_mv[list][ref][blocktype][by][bx][1];
01753 currSlice->motion_cost8[list][ref][block8x8] = *m_cost;
01754 }
01755 }
01756 }
01757
01758 free_mv_block(p_Inp, &mv_block);
01759 }
01760
01761 #if GET_METIME
01762 gettime(&me_time_end);
01763 me_tmp_time = timediff (&me_time_start, &me_time_end);
01764 p_Img->me_tot_time += me_tmp_time;
01765 p_Img->me_time += me_tmp_time;
01766 #endif
01767 }
01768
01769
01770
01771
01772
01773
01774
01775 void Get_Direct_MV_Temporal (Macroblock *currMB)
01776 {
01777 Slice *currSlice = currMB->p_slice;
01778 int block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
01779 short ******all_mvs;
01780 int mv_scale;
01781 int refList;
01782 int ref_idx;
01783 ImageParameters *p_Img = currMB->p_Img;
01784 int64 *refpic = p_Img->enc_picture->ref_pic_num[LIST_0 +currMB->list_offset];
01785
01786 MotionParams *colocated;
01787
01788 if (currMB->list_offset)
01789 {
01790 if(currMB->mbAddrX & 0x01)
01791 {
01792 colocated = &currSlice->p_colocated->bottom;
01793 }
01794 else
01795 {
01796 colocated = &currSlice->p_colocated->top;
01797 }
01798 }
01799 else
01800 {
01801 colocated = &currSlice->p_colocated->frame;
01802 }
01803
01804
01805
01806 for (block_y = 0; block_y < 4; block_y++)
01807 {
01808 pic_block_y = currMB->block_y + block_y;
01809 opic_block_y = (currMB->opix_y >> 2) + block_y;
01810
01811 for (block_x = 0; block_x < 4; block_x++)
01812 {
01813 pic_block_x = currMB->block_x + block_x;
01814 opic_block_x = (currMB->pix_x>>2) + block_x;
01815 all_mvs = currSlice->all_mv;
01816
01817 refList = (colocated->ref_idx[LIST_0][opic_block_y][opic_block_x]== -1 ? LIST_1 : LIST_0);
01818 ref_idx = colocated->ref_idx[refList][opic_block_y][opic_block_x];
01819
01820
01821 if (ref_idx==-1)
01822 {
01823 memset(all_mvs[LIST_0][0][0][block_y][block_x], 0, 2* sizeof(short));
01824 memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2* sizeof(short));
01825 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = 0;
01826 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0;
01827 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
01828 }
01829
01830 else
01831 {
01832 int mapped_idx=INVALIDINDEX;
01833 int iref;
01834
01835 for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], p_Img->listXsize[LIST_0 + currMB->list_offset]); iref++)
01836 {
01837 if (refpic[iref]==colocated->ref_pic_id[refList ][opic_block_y][opic_block_x])
01838 {
01839 mapped_idx=iref;
01840 break;
01841 }
01842 else
01843 {
01844 mapped_idx=INVALIDINDEX;
01845 }
01846 }
01847
01848 if (mapped_idx !=INVALIDINDEX)
01849 {
01850 mv_scale = currSlice->mvscale[LIST_0+currMB->list_offset][mapped_idx];
01851
01852 if (mv_scale==9999)
01853 {
01854
01855 memcpy(all_mvs[LIST_0][0][0][block_y][block_x], colocated->mv[refList][opic_block_y][opic_block_x], 2* sizeof(short));
01856
01857 memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2* sizeof(short));
01858 }
01859 else
01860 {
01861
01862 all_mvs[LIST_0][mapped_idx][0][block_y][block_x][0] = (short) ((mv_scale * colocated->mv[refList][opic_block_y][opic_block_x][0] + 128) >> 8);
01863 all_mvs[LIST_0][mapped_idx][0][block_y][block_x][1] = (short) ((mv_scale * colocated->mv[refList][opic_block_y][opic_block_x][1] + 128) >> 8);
01864
01865 all_mvs[LIST_1][ 0][0][block_y][block_x][0] = (short) (((mv_scale - 256)* colocated->mv[refList][opic_block_y][opic_block_x][0] + 128) >> 8);
01866 all_mvs[LIST_1][ 0][0][block_y][block_x][1] = (short) (((mv_scale - 256)* colocated->mv[refList][opic_block_y][opic_block_x][1] + 128) >> 8);
01867 }
01868
01869
01870 if ( out_of_bounds_mvs(p_Img, all_mvs[LIST_0][mapped_idx][0][block_y][block_x])|| out_of_bounds_mvs(p_Img, all_mvs[LIST_1][0][0][block_y][block_x]))
01871 {
01872 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
01873 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
01874 currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
01875 }
01876 else
01877 {
01878 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = (char) mapped_idx;
01879 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0;
01880 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
01881 }
01882 }
01883 else
01884 {
01885 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
01886 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
01887 currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
01888 }
01889 }
01890 if (p_Img->active_pps->weighted_bipred_idc == 1 && currSlice->direct_pdir[pic_block_y][pic_block_x] == 2)
01891 {
01892 int weight_sum, i;
01893 short l0_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0];
01894 short l1_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1];
01895 for (i=0;i< (p_Img->active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
01896 {
01897 weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
01898 if (weight_sum < -128 || weight_sum > 127)
01899 {
01900 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
01901 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
01902 currSlice->direct_pdir [pic_block_y][pic_block_x] = -1;
01903 break;
01904 }
01905 }
01906 }
01907 }
01908 }
01909 }
01910
01911
01912
01913
01914
01915
01916
01917 void Get_Direct_MV_Spatial_Normal (Macroblock *currMB)
01918 {
01919 Slice *currSlice = currMB->p_slice;
01920 ImageParameters *p_Img = currMB->p_Img;
01921 PicMotionParams *motion = &p_Img->enc_picture->motion;
01922 short l0_refA, l0_refB, l0_refC;
01923 short l1_refA, l1_refB, l1_refC;
01924 short l0_refX,l1_refX;
01925 short pmvfw[2]={0,0},pmvbw[2]={0,0};
01926
01927 int block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
01928 short ******all_mvs;
01929 char *direct_ref_idx;
01930
01931 MotionParams *colocated;
01932 char ** ref_pic_l0 = motion->ref_idx[LIST_0];
01933 char ** ref_pic_l1 = motion->ref_idx[LIST_1];
01934
01935 PixelPos mb[4];
01936 get_neighbors(currMB, mb, 0, 0, 16);
01937
01938 if (currMB->list_offset)
01939 {
01940 if(currMB->mbAddrX & 0x01)
01941 {
01942 colocated = &currSlice->p_colocated->bottom;
01943 }
01944 else
01945 {
01946 colocated = &currSlice->p_colocated->top;
01947 }
01948 }
01949 else
01950 {
01951 colocated = &currSlice->p_colocated->frame;
01952 }
01953
01954 l0_refA = mb[0].available ? ref_pic_l0[mb[0].pos_y][mb[0].pos_x] : -1;
01955 l0_refB = mb[1].available ? ref_pic_l0[mb[1].pos_y][mb[1].pos_x] : -1;
01956 l0_refC = mb[2].available ? ref_pic_l0[mb[2].pos_y][mb[2].pos_x] : -1;
01957
01958 l1_refA = mb[0].available ? ref_pic_l1[mb[0].pos_y][mb[0].pos_x] : -1;
01959 l1_refB = mb[1].available ? ref_pic_l1[mb[1].pos_y][mb[1].pos_x] : -1;
01960 l1_refC = mb[2].available ? ref_pic_l1[mb[2].pos_y][mb[2].pos_x] : -1;
01961
01962 l0_refX = (short) ((l0_refA >= 0 && l0_refB >= 0) ? imin(l0_refA,l0_refB): imax(l0_refA,l0_refB));
01963 l0_refX = (short) ((l0_refX >= 0 && l0_refC >= 0) ? imin(l0_refX,l0_refC): imax(l0_refX,l0_refC));
01964
01965 l1_refX = (short) ((l1_refA >= 0 && l1_refB >= 0) ? imin(l1_refA,l1_refB): imax(l1_refA,l1_refB));
01966 l1_refX = (short) ((l1_refX >= 0 && l1_refC >= 0) ? imin(l1_refX,l1_refC): imax(l1_refX,l1_refC));
01967
01968 if (l0_refX >=0)
01969 currMB->GetMVPredictor (currMB, mb, pmvfw, l0_refX, motion->ref_idx[LIST_0], motion->mv[LIST_0], 0, 0, 16, 16);
01970
01971 if (l1_refX >=0)
01972 currMB->GetMVPredictor (currMB, mb, pmvbw, l1_refX, motion->ref_idx[LIST_1], motion->mv[LIST_1], 0, 0, 16, 16);
01973
01974 for (block_y=0; block_y<4; block_y++)
01975 {
01976 pic_block_y = currMB->block_y + block_y;
01977 opic_block_y = (currMB->opix_y >> 2) + block_y;
01978
01979 for (block_x=0; block_x<4; block_x++)
01980 {
01981 pic_block_x = currMB->block_x + block_x;
01982 direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
01983 opic_block_x = (currMB->pix_x >> 2) + block_x;
01984
01985 all_mvs = currSlice->all_mv;
01986
01987 if (l0_refX >=0)
01988 {
01989 if (!l0_refX && !colocated->moving_block[opic_block_y][opic_block_x])
01990 {
01991 memset(all_mvs[LIST_0][0][0][block_y][block_x], 0, 2 * sizeof(short));
01992 direct_ref_idx[LIST_0]=0;
01993 }
01994 else
01995 {
01996 memcpy(all_mvs[LIST_0][l0_refX][0][block_y][block_x], pmvfw, 2 * sizeof(short));
01997 direct_ref_idx[LIST_0]= (char)l0_refX;
01998 }
01999 }
02000 else
02001 {
02002 memset(all_mvs[LIST_0][0][0][block_y][block_x], 0, 2 * sizeof(short));
02003 direct_ref_idx[LIST_0]=-1;
02004 }
02005
02006 if (l1_refX >=0)
02007 {
02008 if(l1_refX==0 && !colocated->moving_block[opic_block_y][opic_block_x])
02009 {
02010 memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2 * sizeof(short));
02011 direct_ref_idx[LIST_1]= (char)l1_refX;
02012 }
02013 else
02014 {
02015 memcpy(all_mvs[LIST_1][l1_refX][0][block_y][block_x], pmvbw, 2 * sizeof(short));
02016 direct_ref_idx[LIST_1] = (char)l1_refX;
02017 }
02018 }
02019 else
02020 {
02021 memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2 * sizeof(short));
02022 direct_ref_idx[LIST_1] = -1;
02023 }
02024
02025
02026 if (l0_refX < 0 && l1_refX < 0)
02027 {
02028 direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0;
02029 l0_refX = 0;
02030 l1_refX = 0;
02031 }
02032
02033 if (direct_ref_idx[LIST_1] == -1)
02034 currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
02035 else if (direct_ref_idx[LIST_0] == -1)
02036 currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
02037 else if (p_Img->active_pps->weighted_bipred_idc == 1)
02038 {
02039 int weight_sum, i;
02040 Boolean invalid_wp = FALSE;
02041 for (i=0;i< (p_Img->active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
02042 {
02043 weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
02044 if (weight_sum < -128 || weight_sum > 127)
02045 {
02046 invalid_wp = TRUE;
02047 break;
02048 }
02049 }
02050 if (invalid_wp == FALSE)
02051 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
02052 else
02053 {
02054 direct_ref_idx[LIST_0] = -1;
02055 direct_ref_idx[LIST_1] = -1;
02056 currSlice->direct_pdir [pic_block_y][pic_block_x] = -1;
02057 }
02058 }
02059 else
02060 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
02061 }
02062 }
02063 }
02064
02065
02066
02067
02068
02069
02070
02071
02072 void Get_Direct_MV_Spatial_MBAFF (Macroblock *currMB)
02073 {
02074 short l0_refA, l0_refB, l0_refC;
02075 short l1_refA, l1_refB, l1_refC;
02076 short l0_refX,l1_refX;
02077 short pmvfw[2]={0,0},pmvbw[2]={0,0};
02078
02079 int block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
02080 short ******all_mvs;
02081 char *direct_ref_idx;
02082
02083 MotionParams *colocated;
02084 Slice *currSlice = currMB->p_slice;
02085 ImageParameters *p_Img = currMB->p_Img;
02086 PicMotionParams *motion = &p_Img->enc_picture->motion;
02087
02088 char **ref_pic_l0 = motion->ref_idx[LIST_0];
02089 char **ref_pic_l1 = motion->ref_idx[LIST_1];
02090
02091 PixelPos mb[4];
02092 get_neighbors(currMB, mb, 0, 0, 16);
02093
02094 if (currMB->list_offset)
02095 {
02096 if(currMB->mbAddrX & 0x01)
02097 {
02098 colocated = &currSlice->p_colocated->bottom;
02099 }
02100 else
02101 {
02102 colocated = &currSlice->p_colocated->top;
02103 }
02104 }
02105 else
02106 {
02107 colocated = &currSlice->p_colocated->frame;
02108 }
02109
02110 if (currMB->mb_field)
02111 {
02112 l0_refA = mb[0].available
02113 ? (p_Img->mb_data[mb[0].mb_addr].mb_field || ref_pic_l0[mb[0].pos_y][mb[0].pos_x] < 0
02114 ? ref_pic_l0[mb[0].pos_y][mb[0].pos_x]
02115 : ref_pic_l0[mb[0].pos_y][mb[0].pos_x] * 2) : -1;
02116
02117 l0_refB = mb[1].available
02118 ? (p_Img->mb_data[mb[1].mb_addr].mb_field || ref_pic_l0[mb[1].pos_y][mb[1].pos_x] < 0
02119 ? ref_pic_l0[mb[1].pos_y][mb[1].pos_x]
02120 : ref_pic_l0[mb[1].pos_y][mb[1].pos_x] * 2) : -1;
02121
02122 l0_refC = mb[2].available
02123 ? (p_Img->mb_data[mb[2].mb_addr].mb_field || ref_pic_l0[mb[2].pos_y][mb[2].pos_x] < 0
02124 ? ref_pic_l0[mb[2].pos_y][mb[2].pos_x]
02125 : ref_pic_l0[mb[2].pos_y][mb[2].pos_x] * 2) : -1;
02126
02127 l1_refA = mb[0].available
02128 ? (p_Img->mb_data[mb[0].mb_addr].mb_field || ref_pic_l1[mb[0].pos_y][mb[0].pos_x] < 0
02129 ? ref_pic_l1[mb[0].pos_y][mb[0].pos_x]
02130 : ref_pic_l1[mb[0].pos_y][mb[0].pos_x] * 2) : -1;
02131
02132 l1_refB = mb[1].available
02133 ? (p_Img->mb_data[mb[1].mb_addr].mb_field || ref_pic_l1[mb[1].pos_y][mb[1].pos_x] < 0
02134 ? ref_pic_l1[mb[1].pos_y][mb[1].pos_x]
02135 : ref_pic_l1[mb[1].pos_y][mb[1].pos_x] * 2) : -1;
02136
02137 l1_refC = mb[2].available
02138 ? (p_Img->mb_data[mb[2].mb_addr].mb_field || ref_pic_l1[mb[2].pos_y][mb[2].pos_x] < 0
02139 ? ref_pic_l1[mb[2].pos_y][mb[2].pos_x]
02140 : ref_pic_l1[mb[2].pos_y][mb[2].pos_x] * 2) : -1;
02141 }
02142 else
02143 {
02144 l0_refA = mb[0].available
02145 ? (p_Img->mb_data[mb[0].mb_addr].mb_field || ref_pic_l0[mb[0].pos_y][mb[0].pos_x] < 0
02146 ? ref_pic_l0[mb[0].pos_y][mb[0].pos_x] >> 1
02147 : ref_pic_l0[mb[0].pos_y][mb[0].pos_x]) : -1;
02148
02149 l0_refB = mb[1].available
02150 ? (p_Img->mb_data[mb[1].mb_addr].mb_field || ref_pic_l0[mb[1].pos_y][mb[1].pos_x] < 0
02151 ? ref_pic_l0[mb[1].pos_y][mb[1].pos_x] >> 1
02152 : ref_pic_l0[mb[1].pos_y][mb[1].pos_x]) : -1;
02153
02154 l0_refC = mb[2].available
02155 ? (p_Img->mb_data[mb[2].mb_addr].mb_field || ref_pic_l0[mb[2].pos_y][mb[2].pos_x] < 0
02156 ? ref_pic_l0[mb[2].pos_y][mb[2].pos_x] >> 1
02157 : ref_pic_l0[mb[2].pos_y][mb[2].pos_x]) : -1;
02158
02159 l1_refA = mb[0].available
02160 ? (p_Img->mb_data[mb[0].mb_addr].mb_field || ref_pic_l1[mb[0].pos_y][mb[0].pos_x] < 0
02161 ? ref_pic_l1[mb[0].pos_y][mb[0].pos_x] >> 1
02162 : ref_pic_l1[mb[0].pos_y][mb[0].pos_x]) : -1;
02163
02164 l1_refB = mb[1].available
02165 ? (p_Img->mb_data[mb[1].mb_addr].mb_field || ref_pic_l1[mb[1].pos_y][mb[1].pos_x] < 0
02166 ? ref_pic_l1[mb[1].pos_y][mb[1].pos_x] >> 1
02167 : ref_pic_l1[mb[1].pos_y][mb[1].pos_x]) : -1;
02168
02169 l1_refC = mb[2].available
02170 ? (p_Img->mb_data[mb[2].mb_addr].mb_field || ref_pic_l1[mb[2].pos_y][mb[2].pos_x] < 0
02171 ? ref_pic_l1[mb[2].pos_y][mb[2].pos_x] >> 1
02172 : ref_pic_l1[mb[2].pos_y][mb[2].pos_x]) : -1;
02173 }
02174
02175 l0_refX = (short) ((l0_refA >= 0 && l0_refB >= 0) ? imin(l0_refA,l0_refB): imax(l0_refA,l0_refB));
02176 l0_refX = (short) ((l0_refX >= 0 && l0_refC >= 0) ? imin(l0_refX,l0_refC): imax(l0_refX,l0_refC));
02177
02178 l1_refX = (short) ((l1_refA >= 0 && l1_refB >= 0) ? imin(l1_refA,l1_refB): imax(l1_refA,l1_refB));
02179 l1_refX = (short) ((l1_refX >= 0 && l1_refC >= 0) ? imin(l1_refX,l1_refC): imax(l1_refX,l1_refC));
02180
02181 if (l0_refX >=0)
02182 currMB->GetMVPredictor (currMB, mb, pmvfw, l0_refX, motion->ref_idx[LIST_0], motion->mv[LIST_0], 0, 0, 16, 16);
02183
02184 if (l1_refX >=0)
02185 currMB->GetMVPredictor (currMB, mb, pmvbw, l1_refX, motion->ref_idx[LIST_1], motion->mv[LIST_1], 0, 0, 16, 16);
02186
02187 for (block_y=0; block_y<4; block_y++)
02188 {
02189 pic_block_y = currMB->block_y + block_y;
02190 opic_block_y = (currMB->opix_y >> 2) + block_y;
02191
02192 for (block_x=0; block_x<4; block_x++)
02193 {
02194 pic_block_x = currMB->block_x + block_x;
02195 direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
02196 opic_block_x = (currMB->pix_x >> 2) + block_x;
02197
02198 all_mvs = currSlice->all_mv;
02199
02200 if (l0_refX >=0)
02201 {
02202 if (!l0_refX && !colocated->moving_block[opic_block_y][opic_block_x])
02203 {
02204 memset(all_mvs[LIST_0][0][0][block_y][block_x], 0, 2 * sizeof(short));
02205 direct_ref_idx[LIST_0] = 0;
02206 }
02207 else
02208 {
02209 memcpy(all_mvs[LIST_0][l0_refX][0][block_y][block_x], pmvfw, 2 * sizeof(short));
02210 direct_ref_idx[LIST_0] = (char)l0_refX;
02211 }
02212 }
02213 else
02214 {
02215 memset(all_mvs[LIST_0][0][0][block_y][block_x], 0, 2 * sizeof(short));
02216 direct_ref_idx[LIST_0] = -1;
02217 }
02218
02219 if (l1_refX >=0)
02220 {
02221 if(l1_refX==0 && !colocated->moving_block[opic_block_y][opic_block_x])
02222 {
02223 memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2 * sizeof(short));
02224 direct_ref_idx[LIST_1] = (char)l1_refX;
02225 }
02226 else
02227 {
02228 memcpy(all_mvs[LIST_1][l1_refX][0][block_y][block_x], pmvbw, 2 * sizeof(short));
02229 direct_ref_idx[LIST_1] = (char)l1_refX;
02230 }
02231 }
02232 else
02233 {
02234 memset(all_mvs[LIST_1][0][0][block_y][block_x], 0, 2 * sizeof(short));
02235 direct_ref_idx[LIST_1] = -1;
02236 }
02237
02238
02239
02240
02241 if ((out_of_bounds_mvs(p_Img, all_mvs[LIST_0][l0_refX < 0? 0 : l0_refX][0][block_y][block_x])
02242 || out_of_bounds_mvs(p_Img, all_mvs[LIST_1][l1_refX < 0? 0 : l1_refX][0][block_y][block_x])))
02243 {
02244 direct_ref_idx[LIST_0] = -1;
02245 direct_ref_idx[LIST_1] = -1;
02246 currSlice->direct_pdir [pic_block_y][pic_block_x] = -1;
02247 }
02248 else
02249 {
02250 if (l0_refX < 0 && l1_refX < 0)
02251 {
02252 direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0;
02253 l0_refX = 0;
02254 l1_refX = 0;
02255 }
02256
02257 if (direct_ref_idx[LIST_1] == -1)
02258 currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
02259 else if (direct_ref_idx[LIST_0] == -1)
02260 currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
02261 else if (p_Img->active_pps->weighted_bipred_idc == 1)
02262 {
02263 int weight_sum, i;
02264 Boolean invalid_wp = FALSE;
02265 for (i=0;i< (p_Img->active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
02266 {
02267 weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
02268 if (weight_sum < -128 || weight_sum > 127)
02269 {
02270 invalid_wp = TRUE;
02271 break;
02272 }
02273 }
02274 if (invalid_wp == FALSE)
02275 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
02276 else
02277 {
02278 direct_ref_idx[LIST_0] = -1;
02279 direct_ref_idx[LIST_1] = -1;
02280 currSlice->direct_pdir [pic_block_y][pic_block_x] = -1;
02281 }
02282 }
02283 else
02284 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
02285 }
02286 }
02287 }
02288 }