me_fullfast.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:33k
源码类别:

Audio

开发平台:

Visual C++

  1. /*!
  2. *************************************************************************************
  3. * file me_fullfast.c
  4. *
  5. * brief
  6. *    Motion Estimation using Full Search Fast
  7. *
  8. * author
  9. *    Main contributors (see contributors.h for copyright, address and affiliation details)
  10. *      - Alexis Michael Tourapis <alexismt@ieee.org>
  11. *
  12. *************************************************************************************
  13. */
  14. // Includes
  15. #include "contributors.h"
  16. #include <limits.h>
  17. #include "global.h"
  18. #include "image.h"
  19. #include "memalloc.h"
  20. #include "mb_access.h"
  21. #include "refbuf.h"
  22. #include "me_distortion.h"
  23. #include "me_fullsearch.h"
  24. #include "conformance.h"
  25. #include "mv-search.h"
  26. // Define External Global Parameters
  27. extern short*   spiral_search_x;
  28. extern short*   spiral_search_y;
  29. /*****
  30.  *****  static variables for fast integer motion estimation
  31.  *****
  32.  */
  33. static int  **search_setup_done;  //!< flag if all block SAD's have been calculated yet
  34. static int  **search_center_x;    //!< absolute search center for fast full motion search
  35. static int  **search_center_y;    //!< absolute search center for fast full motion search
  36. static int  **pos_00;             //!< position of (0,0) vector
  37. static distpel  *****BlockSAD;        //!< SAD for all blocksize, ref. frames and motion vectors
  38. static int  **max_search_range;
  39. extern void SetMotionVectorPredictor (Macroblock *currMB, short  pmv[2], char   **refPic,
  40.                                       short  ***tmp_mv, short  ref_frame,
  41.                                       int    list,      int mb_x, int mb_y, 
  42.                                       int    blockshape_x, int blockshape_y);
  43. // Functions
  44. /*!
  45.  ***********************************************************************
  46.  * brief
  47.  *    Full pixel block motion search
  48.  ***********************************************************************
  49.  */
  50. /*!
  51.  ***********************************************************************
  52.  * brief
  53.  *    function creating arrays for fast integer motion estimation
  54.  ***********************************************************************
  55.  */
  56. void InitializeFastFullIntegerSearch (void)
  57. {
  58.   int  i, j, k, list;
  59.   int  search_range = params->search_range;
  60.   int  max_pos      = (2*search_range+1) * (2*search_range+1);
  61.   if ((BlockSAD = (distpel*****)malloc (2 * sizeof(distpel****))) == NULL)
  62.     no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD");
  63.   for (list=0; list<2;list++)
  64.   {
  65.     if ((BlockSAD[list] = (distpel****)malloc ((img->max_num_references) * sizeof(distpel***))) == NULL)
  66.       no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD");
  67.     for (i = 0; i < img->max_num_references; i++)
  68.     {
  69.       if ((BlockSAD[list][i] = (distpel***)malloc (8 * sizeof(distpel**))) == NULL)
  70.         no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD");
  71.       for (j = 1; j < 8; j++)
  72.       {
  73.         if ((BlockSAD[list][i][j] = (distpel**)malloc (16 * sizeof(distpel*))) == NULL)
  74.           no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD");
  75.         for (k = 0; k < 16; k++)
  76.         {
  77.           if ((BlockSAD[list][i][j][k] = (distpel*)malloc (max_pos * sizeof(distpel))) == NULL)
  78.             no_mem_exit ("InitializeFastFullIntegerSearch: BlockSAD");
  79.         }
  80.       }
  81.     }
  82.   }
  83.   if ((search_setup_done = (int**)malloc (2*sizeof(int*)))==NULL)
  84.     no_mem_exit ("InitializeFastFullIntegerSearch: search_setup_done");
  85.   if ((search_center_x = (int**)malloc (2*sizeof(int*)))==NULL)
  86.     no_mem_exit ("InitializeFastFullIntegerSearch: search_center_x");
  87.   if ((search_center_y = (int**)malloc (2*sizeof(int*)))==NULL)
  88.     no_mem_exit ("InitializeFastFullIntegerSearch: search_center_y");
  89.   if ((pos_00 = (int**)malloc (2*sizeof(int*)))==NULL)
  90.     no_mem_exit ("InitializeFastFullIntegerSearch: pos_00");
  91.   if ((max_search_range = (int**)malloc (2*sizeof(int*)))==NULL)
  92.     no_mem_exit ("InitializeFastFullIntegerSearch: max_search_range");
  93.   for (list=0; list<2; list++)
  94.   {
  95.     if ((search_setup_done[list] = (int*)malloc ((img->max_num_references)*sizeof(int)))==NULL)
  96.       no_mem_exit ("InitializeFastFullIntegerSearch: search_setup_done");
  97.     if ((search_center_x[list] = (int*)malloc ((img->max_num_references)*sizeof(int)))==NULL)
  98.       no_mem_exit ("InitializeFastFullIntegerSearch: search_center_x");
  99.     if ((search_center_y[list] = (int*)malloc ((img->max_num_references)*sizeof(int)))==NULL)
  100.       no_mem_exit ("InitializeFastFullIntegerSearch: search_center_y");
  101.     if ((pos_00[list] = (int*)malloc ((img->max_num_references)*sizeof(int)))==NULL)
  102.       no_mem_exit ("InitializeFastFullIntegerSearch: pos_00");
  103.     if ((max_search_range[list] = (int*)malloc ((img->max_num_references)*sizeof(int)))==NULL)
  104.       no_mem_exit ("InitializeFastFullIntegerSearch: max_search_range");
  105.   }
  106.   // assign max search ranges for reference frames
  107.   if (params->full_search == 2)
  108.   {
  109.     for (list=0;list<2;list++)
  110.       for (i=0; i<img->max_num_references; i++)
  111.         max_search_range[list][i] = search_range;
  112.   }
  113.   else
  114.   {
  115.     for (list=0;list<2;list++)
  116.     {
  117.       max_search_range[list][0] = search_range;
  118.       for (i=1; i< img->max_num_references; i++)  max_search_range[list][i] = search_range / 2;
  119.     }
  120.   }
  121. }
  122. /*!
  123.  ***********************************************************************
  124.  * brief
  125.  *    function for deleting the arrays for fast integer motion estimation
  126.  ***********************************************************************
  127.  */
  128. void
  129. ClearFastFullIntegerSearch ()
  130. {
  131.   int  i, j, k, list;
  132.   for (list=0; list<2; list++)
  133.   {
  134.     for (i = 0; i < img->max_num_references; i++)
  135.     {
  136.       for (j = 1; j < 8; j++)
  137.       {
  138.         for (k = 0; k < 16; k++)
  139.         {
  140.           free (BlockSAD[list][i][j][k]);
  141.         }
  142.         free (BlockSAD[list][i][j]);
  143.       }
  144.       free (BlockSAD[list][i]);
  145.     }
  146.     free (BlockSAD[list]);
  147.   }
  148.   free (BlockSAD);
  149.   for (list=0; list<2; list++)
  150.   {
  151.     free (search_setup_done[list]);
  152.     free (search_center_x[list]);
  153.     free (search_center_y[list]);
  154.     free (pos_00[list]);
  155.     free (max_search_range[list]);
  156.   }
  157.   free (search_setup_done);
  158.   free (search_center_x);
  159.   free (search_center_y);
  160.   free (pos_00);
  161.   free (max_search_range);
  162. }
  163. /*!
  164.  ***********************************************************************
  165.  * brief
  166.  *    function resetting flags for fast integer motion estimation
  167.  *    (have to be called in start_macroblock())
  168.  ***********************************************************************
  169.  */
  170. void ResetFastFullIntegerSearch ()
  171. {
  172.   int list;
  173.   for (list=0; list<2; list++)
  174.     memset(&search_setup_done [list][0], 0, img->max_num_references * sizeof(int));
  175. }
  176. /*!
  177.  ***********************************************************************
  178.  * brief
  179.  *    calculation of SAD for larger blocks on the basis of 4x4 blocks
  180.  ***********************************************************************
  181.  */
  182. void
  183. SetupLargerBlocks (int list, int refindex, int max_pos)
  184. {
  185. #define ADD_UP_BLOCKS()   _o=*_bo; _i=*_bi; _j=*_bj; for(pos=0;pos<max_pos;pos++) _o[pos] = _i[pos] + _j[pos];
  186. #define INCREMENT(inc)    _bo+=inc; _bi+=inc; _bj+=inc;
  187.   int       pos;
  188.   distpel   **_bo, **_bi, **_bj;
  189.   register distpel *_o,   *_i,   *_j;
  190.   //--- blocktype 6 ---
  191.   _bo = BlockSAD[list][refindex][6];
  192.   _bi = BlockSAD[list][refindex][7];
  193.   _bj = _bi + 4;
  194.   ADD_UP_BLOCKS(); INCREMENT(1);
  195.   ADD_UP_BLOCKS(); INCREMENT(1);
  196.   ADD_UP_BLOCKS(); INCREMENT(1);
  197.   ADD_UP_BLOCKS(); INCREMENT(5);
  198.   ADD_UP_BLOCKS(); INCREMENT(1);
  199.   ADD_UP_BLOCKS(); INCREMENT(1);
  200.   ADD_UP_BLOCKS(); INCREMENT(1);
  201.   ADD_UP_BLOCKS();
  202.   //--- blocktype 5 ---
  203.   _bo = BlockSAD[list][refindex][5];
  204.   _bi = BlockSAD[list][refindex][7];
  205.   _bj = _bi + 1;
  206.   ADD_UP_BLOCKS(); INCREMENT(2);
  207.   ADD_UP_BLOCKS(); INCREMENT(2);
  208.   ADD_UP_BLOCKS(); INCREMENT(2);
  209.   ADD_UP_BLOCKS(); INCREMENT(2);
  210.   ADD_UP_BLOCKS(); INCREMENT(2);
  211.   ADD_UP_BLOCKS(); INCREMENT(2);
  212.   ADD_UP_BLOCKS(); INCREMENT(2);
  213.   ADD_UP_BLOCKS();
  214.   //--- blocktype 4 ---
  215.   _bo = BlockSAD[list][refindex][4];
  216.   _bi = BlockSAD[list][refindex][6];
  217.   _bj = _bi + 1;
  218.   ADD_UP_BLOCKS(); INCREMENT(2);
  219.   ADD_UP_BLOCKS(); INCREMENT(6);
  220.   ADD_UP_BLOCKS(); INCREMENT(2);
  221.   ADD_UP_BLOCKS();
  222.   //--- blocktype 3 ---
  223.   _bo = BlockSAD[list][refindex][3];
  224.   _bi = BlockSAD[list][refindex][4];
  225.   _bj = _bi + 8;
  226.   ADD_UP_BLOCKS(); INCREMENT(2);
  227.   ADD_UP_BLOCKS();
  228.   //--- blocktype 2 ---
  229.   _bo = BlockSAD[list][refindex][2];
  230.   _bi = BlockSAD[list][refindex][4];
  231.   _bj = _bi + 2;
  232.   ADD_UP_BLOCKS(); INCREMENT(8);
  233.   ADD_UP_BLOCKS();
  234.   //--- blocktype 1 ---
  235.   _bo = BlockSAD[list][refindex][1];
  236.   _bi = BlockSAD[list][refindex][3];
  237.   _bj = _bi + 2;
  238.   ADD_UP_BLOCKS();
  239. }
  240. /*!
  241.  ***********************************************************************
  242.  * brief
  243.  *    Setup the fast search for an macroblock
  244.  ***********************************************************************
  245.  */
  246. #define GEN_ME 0
  247. #if GEN_ME
  248. void SetupFastFullPelSearch (Macroblock *currMb, short ref, int list)  // <--  reference frame parameter, list0 or 1
  249. {
  250.   short   pmv[2], mv[2];
  251.   static imgpel   orig_pels[768];
  252.   imgpel  *srcptr = orig_pels;
  253.   int     offset_x, offset_y, range_partly_outside, ref_x, ref_y, pos, abs_x, abs_y, bindex, blky;
  254.   int     max_width, max_height;
  255.   int     img_width, img_height;
  256.   StorablePicture *ref_picture;
  257.   distpel**   block_sad = BlockSAD[list][ref][7];
  258.   int     search_range  = max_search_range[list][ref];
  259.   int     max_pos       = (2*search_range+1) * (2*search_range+1);
  260.   int     list_offset   = img->mb_data[img->current_mb_nr].list_offset;
  261.   int     apply_weights = ( (active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) ||
  262.     (active_pps->weighted_bipred_idc && (img->type == B_SLICE))) && params->UseWeightedReferenceME;
  263.   int abs_y4, abs_x4;
  264.   int   i, j, k;
  265.   int   level_dist = F_PEL + apply_weights * 3;
  266.   int   pixel_x, pixel_y;
  267.   for ( j= img->opix_y; j < img->opix_y + MB_BLOCK_SIZE; j +=BLOCK_SIZE)
  268.   {
  269.     for (pixel_y = j; pixel_y < j + BLOCK_SIZE; pixel_y++)
  270.     {
  271.       memcpy( srcptr, &pCurImg[pixel_y][img->opix_x], BLOCK_SIZE * sizeof(imgpel));
  272.       memcpy( srcptr + 16, &pCurImg[pixel_y][img->opix_x + BLOCK_SIZE], BLOCK_SIZE * sizeof(imgpel));
  273.       memcpy( srcptr + 32, &pCurImg[pixel_y][img->opix_x + 2 * BLOCK_SIZE], BLOCK_SIZE * sizeof(imgpel));
  274.       memcpy( srcptr + 48, &pCurImg[pixel_y][img->opix_x + 3 * BLOCK_SIZE], BLOCK_SIZE * sizeof(imgpel));
  275.       srcptr += BLOCK_SIZE;
  276.     }
  277.     srcptr += 48;
  278.   }
  279.   // storage format is different from that of orig_pic
  280.   // for YUV 4:2:0 we have:
  281.   // YYYY
  282.   // YYYY
  283.   // U U
  284.   //
  285.   // V V
  286.   //
  287.   if (ChromaMEEnable)
  288.   {
  289.     imgpel *auxptr;
  290.     int   uv;
  291.     int   bsx_c = BLOCK_SIZE >> (chroma_shift_x - 2);
  292.     int   bsy_c = BLOCK_SIZE >> (chroma_shift_y - 2);
  293.     int   pic_pix_x_c = img->opix_x >> (chroma_shift_x - 2);
  294.     int   pic_pix_y_c = img->opix_y >> (chroma_shift_y - 2);
  295.     // copy the original cmp1 and cmp2 data to the orig_pic matrix
  296.     // This seems to be wrong.
  297.     for (uv = 1; uv < 3; uv++)
  298.     {
  299.       srcptr = auxptr = orig_pels + (256 << (uv - 1));
  300.       for ( pixel_y = 0, i = 0; i < (BLOCK_SIZE >> (chroma_shift_y - 2)); i++, pixel_y += bsy_c )
  301.       {
  302.         for ( pixel_x = 0, k = 0; k < (BLOCK_SIZE >> (chroma_shift_x - 2)); k++, pixel_x += bsx_c )
  303.         {
  304.           srcptr = auxptr;
  305.           for (j = 0; j < bsy_c; j++)
  306.           {
  307.             memcpy( srcptr, &pImgOrg[uv][pic_pix_y_c + pixel_y + j][pic_pix_x_c + pixel_x], bsx_c * sizeof(imgpel));
  308.             srcptr += bsx_c;
  309.           }
  310.           auxptr += MB_BLOCK_SIZE;
  311.         }
  312.       }
  313.     }
  314.   }
  315.   ref_picture     = listX[list+list_offset][ref];
  316.   ref_access_method = FAST_ACCESS;
  317.   //===== Use weighted Reference for ME ====
  318.   ref_pic_sub.luma = ref_picture->p_curr_img_sub;
  319.   if (apply_weights)
  320.   {
  321.     weight_luma = wp_weight[list + list_offset][ref][0];
  322.     offset_luma = wp_offset[list + list_offset][ref][0];
  323.   }
  324.   if ( ChromaMEEnable)
  325.   {
  326.     ref_pic_sub.crcb[0] = ref_picture->imgUV_sub[0];
  327.     ref_pic_sub.crcb[1] = ref_picture->imgUV_sub[1];
  328.     width_pad_cr  = ref_picture->size_x_cr_pad;
  329.     height_pad_cr = ref_picture->size_y_cr_pad;
  330.     if (apply_weights)
  331.     {
  332.       weight_cr[0] = wp_weight[list + list_offset][ref][1];
  333.       weight_cr[1] = wp_weight[list + list_offset][ref][2];
  334.       offset_cr[0] = wp_offset[list + list_offset][ref][1];
  335.       offset_cr[1] = wp_offset[list + list_offset][ref][2];
  336.     }
  337.   }
  338.   max_width     = ref_picture->size_x - 17;
  339.   max_height    = ref_picture->size_y - 17;
  340.   img_width     = ref_picture->size_x;
  341.   img_height    = ref_picture->size_y;
  342.   width_pad     = ref_picture->size_x_pad;
  343.   height_pad    = ref_picture->size_y_pad;
  344.   //===== get search center: predictor of 16x16 block =====
  345.   SetMotionVectorPredictor (currMB, pmv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, 0, 0, 16, 16);
  346.   mv[0] = pmv[0] / 4;
  347.   mv[1] = pmv[1] / 4;
  348.   if (!params->rdopt)
  349.   {
  350.     //--- correct center so that (0,0) vector is inside ---
  351.     mv[0] = iClip3(-search_range, search_range, mv[0]);
  352.     mv[1] = iClip3(-search_range, search_range, mv[1]);
  353.   }
  354.   clip_mv_range(img, search_range, mv, F_PEL);
  355.   search_center_x[list][ref] = mv[0] + img->opix_x;
  356.   search_center_y[list][ref] = mv[1] + img->opix_y;
  357.   offset_x = search_center_x[list][ref];
  358.   offset_y = search_center_y[list][ref];
  359.   //===== check if whole search range is inside image =====
  360.   if (offset_x >= search_range && offset_x <= max_width  - search_range &&
  361.     offset_y >= search_range && offset_y <= max_height - search_range   )
  362.   {
  363.     range_partly_outside = 0;
  364.   }
  365.   else
  366.   {
  367.     range_partly_outside = 1;
  368.   }
  369.   //===== determine position of (0,0)-vector =====
  370.   if (!params->rdopt)
  371.   {
  372.     ref_x = img->opix_x - offset_x;
  373.     ref_y = img->opix_y - offset_y;
  374.     for (pos = 0; pos < max_pos; pos++)
  375.     {
  376.       if (ref_x == spiral_search_x[pos] &&
  377.         ref_y == spiral_search_y[pos])
  378.       {
  379.         pos_00[list][ref] = pos;
  380.         break;
  381.       }
  382.     }
  383.   }
  384.   //===== loop over search range (spiral search): get blockwise SAD =====
  385.   for (pos = 0; pos < max_pos; pos++)
  386.   {
  387.     abs_y = offset_y + spiral_search_y[pos];
  388.     abs_x = offset_x + spiral_search_x[pos];
  389.     abs_y4 = (abs_y + IMG_PAD_SIZE) << 2;
  390.     abs_x4 = (abs_x + IMG_PAD_SIZE) << 2;
  391.     if (range_partly_outside)
  392.     {
  393.       if (abs_y >= 0 && abs_y <= max_height &&
  394.         abs_x >= 0 && abs_x <= max_width    )
  395.       {
  396.         ref_access_method = FAST_ACCESS;
  397.       }
  398.       else
  399.       {
  400.         ref_access_method = UMV_ACCESS;
  401.       }
  402.     }
  403.     srcptr = orig_pels;
  404.     bindex = 0;
  405.     for (blky = 0; blky < 4; blky++)
  406.     {
  407.       block_sad[bindex++][pos] = computeUniPred[level_dist](srcptr, 4, 4, INT_MAX, abs_x4,      abs_y4);
  408.       srcptr += 16;
  409.       block_sad[bindex++][pos] = computeUniPred[level_dist](srcptr, 4, 4, INT_MAX, abs_x4 + 16, abs_y4);
  410.       srcptr += 16;
  411.       block_sad[bindex++][pos] = computeUniPred[level_dist](srcptr, 4, 4, INT_MAX, abs_x4 + 32, abs_y4);
  412.       srcptr += 16;
  413.       block_sad[bindex++][pos] = computeUniPred[level_dist](srcptr, 4, 4, INT_MAX, abs_x4 + 48, abs_y4);
  414.       srcptr += 16;
  415.       abs_y4 += 16;
  416.     }
  417.   }
  418.   //===== combine SAD's for larger block types =====
  419.   SetupLargerBlocks (list, ref, max_pos);
  420.   //===== set flag marking that search setup have been done =====
  421.   search_setup_done[list][ref] = 1;
  422. }
  423. #else
  424. void SetupFastFullPelSearch (Macroblock *currMB, short ref, int list)  // <--  reference frame parameter, list0 or 1
  425. {
  426.   short   pmv[2];
  427.   static imgpel orig_pels[768];
  428.   imgpel  *srcptr = orig_pels, *refptr;
  429.   int     k, x, y;
  430.   int     abs_y4, abs_x4;
  431.   int     offset_x, offset_y, range_partly_outside, ref_x, ref_y, pos, abs_x, abs_y, bindex, blky;
  432.   int     LineSadBlk0, LineSadBlk1, LineSadBlk2, LineSadBlk3;
  433.   int     max_width, max_height;
  434.   int     img_width, img_height;
  435.   StorablePicture *ref_picture;
  436.   distpel**   block_sad = BlockSAD[list][ref][7];
  437.   int     search_range  = max_search_range[list][ref];
  438.   int     max_pos       = (2*search_range+1) * (2*search_range+1);
  439.   int     list_offset   = img->mb_data[img->current_mb_nr].list_offset;
  440.   int     apply_weights = ( (active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) ||
  441.     (active_pps->weighted_bipred_idc && (img->type == B_SLICE))) && params->UseWeightedReferenceME;
  442.   int     weighted_pel;
  443.   int *dist_method = params->MEErrorMetric[0] ? img->quad : byte_abs;
  444.   ref_picture     = listX[list+list_offset][ref];
  445.   ref_access_method = FAST_ACCESS;
  446.   ref_pic_sub.luma = ref_picture->p_curr_img_sub;
  447.   max_width     = ref_picture->size_x - 17;
  448.   max_height    = ref_picture->size_y - 17;
  449.   img_width     = ref_picture->size_x;
  450.   img_height    = ref_picture->size_y;
  451.   width_pad     = ref_picture->size_x_pad;
  452.   height_pad    = ref_picture->size_y_pad;
  453.   if (apply_weights)
  454.   {
  455.     weight_luma = wp_weight[list + list_offset][ref][0];
  456.     offset_luma = wp_offset[list + list_offset][ref][0];
  457.   }
  458.   if ( ChromaMEEnable)
  459.   {
  460.     ref_pic_sub.crcb[0] = ref_picture->imgUV_sub[0];
  461.     ref_pic_sub.crcb[1] = ref_picture->imgUV_sub[1];
  462.     width_pad_cr  = ref_picture->size_x_cr_pad;
  463.     height_pad_cr = ref_picture->size_y_cr_pad;
  464.     if (apply_weights)
  465.     {
  466.       weight_cr[0] = wp_weight[list + list_offset][ref][1];
  467.       weight_cr[1] = wp_weight[list + list_offset][ref][2];
  468.       offset_cr[0] = wp_offset[list + list_offset][ref][1];
  469.       offset_cr[1] = wp_offset[list + list_offset][ref][2];
  470.     }
  471.   }
  472.   //===== get search center: predictor of 16x16 block =====
  473.   SetMotionVectorPredictor (currMB, pmv, enc_picture->motion.ref_idx[list], enc_picture->motion.mv[list], ref, list, 0, 0, 16, 16);
  474.   search_center_x[list][ref] = pmv[0] / 4;
  475.   search_center_y[list][ref] = pmv[1] / 4;
  476.   if (!params->rdopt)
  477.   {
  478.     //--- correct center so that (0,0) vector is inside ---
  479.     search_center_x[list][ref] = iClip3(-search_range, search_range, search_center_x[list][ref]);
  480.     search_center_y[list][ref] = iClip3(-search_range, search_range, search_center_y[list][ref]);
  481.   }
  482.   search_center_x[list][ref] = iClip3(-2047 + search_range, 2047 - search_range, search_center_x[list][ref]);
  483.   search_center_y[list][ref] = iClip3(LEVELMVLIMIT[img->LevelIndex][0] + search_range, LEVELMVLIMIT[img->LevelIndex][1]  - search_range, search_center_y[list][ref]);
  484.   search_center_x[list][ref] += img->opix_x;
  485.   search_center_y[list][ref] += img->opix_y;
  486.   offset_x = search_center_x[list][ref];
  487.   offset_y = search_center_y[list][ref];
  488.   //===== copy original block for fast access =====
  489.   for   (y = img->opix_y; y < img->opix_y+MB_BLOCK_SIZE; y++)
  490.   {
  491.     memcpy(srcptr, &pCurImg[y][img->opix_x], MB_BLOCK_SIZE * sizeof(imgpel));
  492.     srcptr += MB_BLOCK_SIZE;
  493.   }
  494.   if ( ChromaMEEnable)
  495.   {
  496.     for (k = 1; k < 3; k++)
  497.     {
  498.       for   (y = img->opix_c_y; y < img->opix_c_y + img->mb_cr_size_y; y++)
  499.       {
  500.         memcpy(srcptr, &pImgOrg[k][y][img->opix_c_x], img->mb_cr_size_x * sizeof(imgpel));
  501.         srcptr += img->mb_cr_size_x;
  502.       }
  503.     }
  504.   }
  505.   //===== check if whole search range is inside image =====
  506.   if (offset_x >= search_range && offset_x <= max_width  - search_range &&
  507.     offset_y >= search_range && offset_y <= max_height - search_range   )
  508.   {
  509.     range_partly_outside = 0;
  510.   }
  511.   else
  512.   {
  513.     range_partly_outside = 1;
  514.   }
  515.   //===== determine position of (0,0)-vector =====
  516.   if (!params->rdopt)
  517.   {
  518.     ref_x = img->opix_x - offset_x;
  519.     ref_y = img->opix_y - offset_y;
  520.     for (pos = 0; pos < max_pos; pos++)
  521.     {
  522.       if (ref_x == spiral_search_x[pos] &&
  523.         ref_y == spiral_search_y[pos])
  524.       {
  525.         pos_00[list][ref] = pos;
  526.         break;
  527.       }
  528.     }
  529.   }
  530.   //===== loop over search range (spiral search): get blockwise SAD =====
  531.   for (pos = 0; pos < max_pos; pos++)
  532.   {
  533.     abs_y = offset_y + spiral_search_y[pos];
  534.     abs_x = offset_x + spiral_search_x[pos];
  535.     abs_y4 = (abs_y + IMG_PAD_SIZE) << 2;
  536.     abs_x4 = (abs_x + IMG_PAD_SIZE) << 2;
  537.     if (range_partly_outside)
  538.     {
  539.       if (abs_y >= 0 && abs_y <= max_height&&
  540.         abs_x >= 0 && abs_x <= max_width  )
  541.       {
  542.         ref_access_method = FAST_ACCESS;
  543.       }
  544.       else
  545.       {
  546.         ref_access_method = UMV_ACCESS;
  547.       }
  548.     }
  549.     if (apply_weights)
  550.     {
  551.       srcptr = orig_pels;
  552.       bindex = 0;
  553.       refptr = get_line[ref_access_method] (ref_pic_sub.luma, abs_y4, abs_x4);
  554.       for (blky = 0; blky < 4; blky++)
  555.       {
  556.         LineSadBlk0 = LineSadBlk1 = LineSadBlk2 = LineSadBlk3 = 0;
  557.         for (y = 0; y < 4; y++)
  558.         {
  559.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  560.           LineSadBlk0 += dist_method [weighted_pel - *srcptr++];
  561.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  562.           LineSadBlk0 += dist_method [weighted_pel - *srcptr++];
  563.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  564.           LineSadBlk0 += dist_method [weighted_pel - *srcptr++];
  565.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  566.           LineSadBlk0 += dist_method [weighted_pel - *srcptr++];
  567.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  568.           LineSadBlk1 += dist_method [weighted_pel - *srcptr++];
  569.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  570.           LineSadBlk1 += dist_method [weighted_pel - *srcptr++];
  571.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  572.           LineSadBlk1 += dist_method [weighted_pel - *srcptr++];
  573.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  574.           LineSadBlk1 += dist_method [weighted_pel - *srcptr++];
  575.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  576.           LineSadBlk2 += dist_method [weighted_pel - *srcptr++];
  577.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  578.           LineSadBlk2 += dist_method [weighted_pel - *srcptr++];
  579.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  580.           LineSadBlk2 += dist_method [weighted_pel - *srcptr++];
  581.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  582.           LineSadBlk2 += dist_method [weighted_pel - *srcptr++];
  583.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  584.           LineSadBlk3 += dist_method [weighted_pel - *srcptr++];
  585.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  586.           LineSadBlk3 += dist_method [weighted_pel - *srcptr++];
  587.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  588.           LineSadBlk3 += dist_method [weighted_pel - *srcptr++];
  589.           weighted_pel = iClip1( img->max_imgpel_value, ((weight_luma * *refptr++  + wp_luma_round) >> luma_log_weight_denom) + offset_luma);
  590.           LineSadBlk3 += dist_method [weighted_pel - *srcptr++];
  591.           refptr += img_padded_size_x - MB_BLOCK_SIZE;
  592.         }
  593.         block_sad[bindex++][pos] = LineSadBlk0;
  594.         block_sad[bindex++][pos] = LineSadBlk1;
  595.         block_sad[bindex++][pos] = LineSadBlk2;
  596.         block_sad[bindex++][pos] = LineSadBlk3;
  597.       }
  598.       if (ChromaMEEnable)
  599.       {
  600.         int max_imgpel_value_uv = img->max_imgpel_value_comp[1];
  601.         for (k = 0; k < 2; k ++)
  602.         {
  603.           bindex = 0;
  604.           refptr = get_crline[ref_access_method] (ref_pic_sub.crcb[k], abs_y4, abs_x4);
  605.           for (blky = 0; blky < 4; blky++)
  606.           {
  607.             LineSadBlk0 = LineSadBlk1 = LineSadBlk2 = LineSadBlk3 = 0;
  608.             for (y = 0; y < img->mb_cr_size_y; y+=BLOCK_SIZE)
  609.             {
  610.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  611.               {
  612.                 weighted_pel = iClip1( max_imgpel_value_uv, ((weight_cr[k] * *refptr++  + wp_chroma_round) >> chroma_log_weight_denom) + offset_cr[k]);
  613.                 LineSadBlk0 += dist_method [weighted_pel - *srcptr++];
  614.               }
  615.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  616.               {
  617.                 weighted_pel = iClip1( max_imgpel_value_uv, ((weight_cr[k] * *refptr++  + wp_chroma_round) >> chroma_log_weight_denom) + offset_cr[k]);
  618.                 LineSadBlk1 += dist_method [weighted_pel - *srcptr++];
  619.               }
  620.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  621.               {
  622.                 weighted_pel = iClip1( max_imgpel_value_uv, ((weight_cr[k] * *refptr++  + wp_chroma_round) >> chroma_log_weight_denom) + offset_cr[k]);
  623.                 LineSadBlk2 += dist_method [weighted_pel - *srcptr++];
  624.               }
  625.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  626.               {
  627.                 weighted_pel = iClip1( max_imgpel_value_uv, ((weight_cr[k] * *refptr++  + wp_chroma_round) >> chroma_log_weight_denom) + offset_cr[k]);
  628.                 LineSadBlk3 += dist_method [weighted_pel - *srcptr++];
  629.               }
  630.               refptr += img_cr_padded_size_x - img->mb_cr_size_x;
  631.             }
  632.             block_sad[bindex++][pos] += LineSadBlk0;
  633.             block_sad[bindex++][pos] += LineSadBlk1;
  634.             block_sad[bindex++][pos] += LineSadBlk2;
  635.             block_sad[bindex++][pos] += LineSadBlk3;
  636.           }
  637.         }
  638.       }
  639.     }
  640.     else
  641.     {
  642.       srcptr = orig_pels;
  643.       bindex = 0;
  644.       refptr = get_line[ref_access_method] (ref_pic_sub.luma, abs_y4, abs_x4);
  645.       for (blky = 0; blky < 4; blky++)
  646.       {
  647.         LineSadBlk0 = LineSadBlk1 = LineSadBlk2 = LineSadBlk3 = 0;
  648.         for (y = 0; y < 4; y++)
  649.         {
  650.           LineSadBlk0 += dist_method [*refptr++ - *srcptr++];
  651.           LineSadBlk0 += dist_method [*refptr++ - *srcptr++];
  652.           LineSadBlk0 += dist_method [*refptr++ - *srcptr++];
  653.           LineSadBlk0 += dist_method [*refptr++ - *srcptr++];
  654.           LineSadBlk1 += dist_method [*refptr++ - *srcptr++];
  655.           LineSadBlk1 += dist_method [*refptr++ - *srcptr++];
  656.           LineSadBlk1 += dist_method [*refptr++ - *srcptr++];
  657.           LineSadBlk1 += dist_method [*refptr++ - *srcptr++];
  658.           LineSadBlk2 += dist_method [*refptr++ - *srcptr++];
  659.           LineSadBlk2 += dist_method [*refptr++ - *srcptr++];
  660.           LineSadBlk2 += dist_method [*refptr++ - *srcptr++];
  661.           LineSadBlk2 += dist_method [*refptr++ - *srcptr++];
  662.           LineSadBlk3 += dist_method [*refptr++ - *srcptr++];
  663.           LineSadBlk3 += dist_method [*refptr++ - *srcptr++];
  664.           LineSadBlk3 += dist_method [*refptr++ - *srcptr++];
  665.           LineSadBlk3 += dist_method [*refptr++ - *srcptr++];
  666.           refptr += img_padded_size_x - MB_BLOCK_SIZE;
  667.         }
  668.         block_sad[bindex++][pos] = LineSadBlk0;
  669.         block_sad[bindex++][pos] = LineSadBlk1;
  670.         block_sad[bindex++][pos] = LineSadBlk2;
  671.         block_sad[bindex++][pos] = LineSadBlk3;
  672.       }
  673.       if (ChromaMEEnable)
  674.       {
  675.         for (k = 0; k < 2; k ++)
  676.         {
  677.           bindex = 0;
  678.           refptr = get_crline[ref_access_method] (ref_pic_sub.crcb[k], abs_y4, abs_x4);
  679.           for (blky = 0; blky < 4; blky++)
  680.           {
  681.             LineSadBlk0 = LineSadBlk1 = LineSadBlk2 = LineSadBlk3 = 0;
  682.             for (y = 0; y < img->mb_cr_size_y; y+=BLOCK_SIZE)
  683.             {
  684.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  685.               {
  686.                 LineSadBlk0 += dist_method [*refptr++ - *srcptr++];
  687.               }
  688.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  689.               {
  690.                 LineSadBlk1 += dist_method [*refptr++ - *srcptr++];
  691.               }
  692.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  693.               {
  694.                 LineSadBlk2 += dist_method [*refptr++ - *srcptr++];
  695.               }
  696.               for (x = 0; x < img->mb_cr_size_x; x += BLOCK_SIZE)
  697.               {
  698.                 LineSadBlk3 += dist_method [*refptr++ - *srcptr++];
  699.               }
  700.               refptr += img_cr_padded_size_x - img->mb_cr_size_x;
  701.             }
  702.             block_sad[bindex++][pos] += LineSadBlk0;
  703.             block_sad[bindex++][pos] += LineSadBlk1;
  704.             block_sad[bindex++][pos] += LineSadBlk2;
  705.             block_sad[bindex++][pos] += LineSadBlk3;
  706.           }
  707.         }
  708.       }
  709.     }
  710.   }
  711.   //===== combine SAD's for larger block types =====
  712.   SetupLargerBlocks (list, ref, max_pos);
  713.   //===== set flag marking that search setup have been done =====
  714.   search_setup_done[list][ref] = 1;
  715. }
  716. #endif
  717. /*!
  718.  ***********************************************************************
  719.  * brief
  720.  *    Fast Full pixel block motion search
  721.  ***********************************************************************
  722.  */
  723. int                                                     //  ==> minimum motion cost after search
  724. FastFullPelBlockMotionSearch (Macroblock *currMB,       // <--  current Macroblock
  725.                               imgpel*   orig_pic,       // <--  not used
  726.                               short     ref,            // <--  reference frame (0... or -1 (backward))
  727.                               int       list,
  728.                               int       list_offset,    // <--  MBAFF list offset
  729.                               char   ***refPic,         // <--  reference array
  730.                               short ****tmp_mv,         // <--  mv array
  731.                               int       pic_pix_x,      // <--  absolute x-coordinate of regarded AxB block
  732.                               int       pic_pix_y,      // <--  absolute y-coordinate of regarded AxB block
  733.                               int       blocktype,      // <--  block type (1-16x16 ... 7-4x4)
  734.                               short     pred_mv[2],     // <--  motion vector predictor (x) in sub-pel units
  735.                               short     mv[2],          // <--> in: search center (x) / out: motion vector (x) - in pel units
  736.                               int       search_range,   // <--  1-d search range in pel units
  737.                               int       min_mcost,      // <--  minimum motion cost (cost for center or huge value)
  738.                               int       lambda_factor,  // <--  lagrangian parameter for determining motion cost
  739.                               int       apply_weights
  740.                               )
  741. {
  742.   int   pos, offset_x, offset_y, cand_x, cand_y, mcost;
  743.   int   max_pos       = (2*search_range+1)*(2*search_range+1);              // number of search positions
  744.   int   best_pos      = 0;                                                  // position with minimum motion cost
  745.   int   block_index;                                                        // block index for indexing SAD array
  746.   distpel*  block_sad;                                                          // pointer to SAD array
  747.   block_index   = (pic_pix_y-img->opix_y)+((pic_pix_x-img->opix_x)>>2); // block index for indexing SAD array
  748.   block_sad     = BlockSAD[list][ref][blocktype][block_index];         // pointer to SAD array
  749.   //===== set up fast full integer search if needed / set search center =====
  750.   if (!search_setup_done[list][ref])
  751.   {
  752.     SetupFastFullPelSearch (currMB, ref, list);
  753.   }
  754.   offset_x = search_center_x[list][ref] - img->opix_x;
  755.   offset_y = search_center_y[list][ref] - img->opix_y;
  756.   //===== cost for (0,0)-vector: it is done before, because MVCost can be negative =====
  757.   if (!params->rdopt)
  758.   {
  759.     mcost = block_sad[pos_00[list][ref]] + MV_COST_SMP (lambda_factor, 0, 0, pred_mv[0], pred_mv[1]);
  760.     if (mcost < min_mcost)
  761.     {
  762.       min_mcost = mcost;
  763.       best_pos  = pos_00[list][ref];
  764.     }
  765.   }
  766.   //===== loop over all search positions =====
  767.   for (pos=0; pos<max_pos; pos++, block_sad++)
  768.   {
  769.     //--- check residual cost ---
  770.     if (*block_sad < min_mcost)
  771.     {
  772.       //--- get motion vector cost ---
  773.       cand_x = (offset_x + spiral_search_x[pos])<<2;
  774.       cand_y = (offset_y + spiral_search_y[pos])<<2;
  775.       mcost  = *block_sad;
  776.       mcost += MV_COST_SMP (lambda_factor, cand_x, cand_y, pred_mv[0], pred_mv[1]);
  777.       //--- check motion cost ---
  778.       if (mcost < min_mcost)
  779.       {
  780.         min_mcost = mcost;
  781.         best_pos  = pos;
  782.       }
  783.     }
  784.   }
  785.   //===== set best motion vector and return minimum motion cost =====
  786.   mv[0] = offset_x + spiral_search_x[best_pos];
  787.   mv[1] = offset_y + spiral_search_y[best_pos];
  788.   return min_mcost;
  789. }