⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mv-search.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:

/*!
 *************************************************************************************
 * \file mv-search.c
 *
 * \brief
 *    Motion Vector Search, unified for B and P Pictures
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *      - Stephan Wenger                  <stewe@cs.tu-berlin.de>
 *      - Inge Lille-Langoy               <inge.lille-langoy@telenor.com>
 *      - Rickard Sjoberg                 <rickard.sjoberg@era.ericsson.se>
 *      - Stephan Wenger                  <stewe@cs.tu-berlin.de>
 *      - Jani Lainema                    <jani.lainema@nokia.com>
 *      - Detlev Marpe                    <marpe@hhi.de>
 *      - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *      - Heiko Schwarz                   <hschwarz@hhi.de>
 *      - Alexis Michael Tourapis         <alexismt@ieee.org>
 *
 *************************************************************************************
*/

#include "contributors.h"

#include <math.h>
#include <limits.h>
#include <time.h>
#include <sys/timeb.h>

#include "global.h"

#include "image.h"
#include "mv-search.h"
#include "refbuf.h"
#include "memalloc.h"
#include "mb_access.h"
#include "macroblock.h"
#include "mc_prediction.h"
#include "conformance.h"

// Motion estimation distortion header file
#include "me_distortion.h"

// Motion estimation search algorithms
#include "me_epzs.h"
#include "me_fullfast.h"
#include "me_fullsearch.h"
#include "me_umhex.h"
#include "me_umhexsmp.h"
#include "rdoq.h"


// Statistics, temporary
int     max_mvd;
short*  spiral_search_x;
short*  spiral_search_y;
short*  spiral_hpel_search_x;
short*  spiral_hpel_search_y;

int*    mvbits;
int*    refbits;
int*    byte_abs;
int**** motion_cost;
int     byte_abs_range;

static int diff  [16];
static int diff64[64];
static imgpel orig_pic [768];
int (*IntPelME)       (Macroblock *, imgpel *, short, int, int, char ***, short ****,
                       int, int, int, short[2], short[2], int, int, int, int);

int (*BiPredME)       (Macroblock *, imgpel *, short, int, int, char  ***, short  ****,
                       int, int, int, short[2], short[2], short[2], short[2], int, int, int, int, int);

int (*SubPelBiPredME) (imgpel* orig_pic, short ref, int list, int pic_pix_x, int pic_pix_y,
                       int blocktype, short pred_mv1[2], short pred_mv2[2], short mv1[2], short mv2[2], 
                       int search_pos2, int search_pos4, int min_mcost, int* lambda_factor, int apply_weights);
int (*SubPelME)       (imgpel* orig_pic, short ref, int list, int list_offset, int pic_pix_x, int pic_pix_y, 
                       int blocktype, short pred_mv[2], short mv[2], 
                       int search_pos2, int search_pos4, int min_mcost, int* lambda_factor, int apply_weights);


int BlockMotionSearch (Macroblock *currMB, short,int,int,int,int,int, int*);
int BiPredBlockMotionSearch(Macroblock *currMB, short[2], short*, short, int, int, int, int , int, int, int*);

int GetSkipCostMB     (Macroblock *currMB);

extern ColocatedParams *Co_located;
extern const short block_type_shift_factor[8];

/*!
 ************************************************************************
 * \brief
 *    Initialize ME engine
 ************************************************************************
 */
void init_ME_engine(int SearchMode)
{
  switch (SearchMode)
  {
   case EPZS:
     IntPelME       = EPZSPelBlockMotionSearch;
     BiPredME       = EPZSBiPredBlockMotionSearch;
     SubPelBiPredME = (params->EPZSSubPelMEBiPred) ? EPZSSubPelBlockSearchBiPred : SubPelBlockSearchBiPred;
     SubPelME       = (params->EPZSSubPelME) ? EPZSSubPelBlockMotionSearch : SubPelBlockMotionSearch;
     break;
   case UM_HEX:
     IntPelME       = UMHEXIntegerPelBlockMotionSearch;
     BiPredME       = UMHEXBipredIntegerPelBlockMotionSearch;
     SubPelBiPredME = SubPelBlockSearchBiPred;
     SubPelME       = UMHEXSubPelBlockME;
     break;
   case UM_HEX_SIMPLE:
     IntPelME       = smpUMHEXIntegerPelBlockMotionSearch;
     BiPredME       = smpUMHEXBipredIntegerPelBlockMotionSearch;
     SubPelBiPredME = SubPelBlockSearchBiPred;
     SubPelME       = smpUMHEXSubPelBlockME;
     break;
   case FULL_SEARCH:
     IntPelME       = FullPelBlockMotionSearch;
     BiPredME       = FullPelBlockMotionBiPred;
     SubPelBiPredME = SubPelBlockSearchBiPred;
     SubPelME       = SubPelBlockMotionSearch;
     break;
   case FAST_FULL_SEARCH:
   default:
     IntPelME       = FastFullPelBlockMotionSearch;
     BiPredME       = FullPelBlockMotionBiPred;
     SubPelBiPredME = SubPelBlockSearchBiPred;
     SubPelME       = SubPelBlockMotionSearch;
     break;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Prepare Motion Estimation parameters for single list ME
 ************************************************************************
 */
void PrepareMEParams(int apply_weights, int ChromaMEEnable, int list, int ref)
{
  if (apply_weights)
  {
    weight_luma = wp_weight[list][ref][0];
    offset_luma = wp_offset[list][ref][0];

    if ( ChromaMEEnable)
    {
      weight_cr[0] = wp_weight[list][ref][1];
      weight_cr[1] = wp_weight[list][ref][2];
      offset_cr[0] = wp_offset[list][ref][1];
      offset_cr[1] = wp_offset[list][ref][2];
    }
  }
}

/*!
 ************************************************************************
 * \brief
 *    Prepare Motion Estimation parameters for bipred list ME
 ************************************************************************
 */
void PrepareBiPredMEParams(int apply_weights, int ChromaMEEnable, int list, int list_offset, int ref)
{
  if (apply_weights)
  {
    if (list == LIST_0)
    {
      weight1  = wbp_weight[list_offset         ][ref][0][0];
      weight2  = wbp_weight[list_offset + LIST_1][ref][0][0];
      offsetBi = (wp_offset[list_offset         ][ref][0] + wp_offset[list_offset + LIST_1][ref][0] + 1)>>1;

      if ( ChromaMEEnable)
      {
        weight1_cr[0] = wbp_weight[list_offset         ][ref][0][1];
        weight1_cr[1] = wbp_weight[list_offset         ][ref][0][2];
        weight2_cr[0] = wbp_weight[list_offset + LIST_1][ref][0][1];
        weight2_cr[1] = wbp_weight[list_offset + LIST_1][ref][0][2];
   
        offsetBi_cr[0] = (wp_offset[list_offset        ][ref][1] + wp_offset[list_offset + LIST_1][ref][1] + 1) >> 1;
        offsetBi_cr[1] = (wp_offset[list_offset        ][ref][2] + wp_offset[list_offset + LIST_1][ref][2] + 1) >> 1;
      }
    }
    else
    {
      weight1  = wbp_weight[list_offset + LIST_1][0  ][ref][0];
      weight2  = wbp_weight[list_offset         ][0  ][ref][0];
      offsetBi = (wp_offset[list_offset + LIST_1][0][0] + wp_offset[list_offset][0][0] + 1)>>1;

      if ( ChromaMEEnable)
      {
        weight1_cr[0] = wbp_weight[list_offset + LIST_1][0  ][ref][1];
        weight1_cr[1] = wbp_weight[list_offset + LIST_1][0  ][ref][2];
        weight2_cr[0] = wbp_weight[list_offset         ][0  ][ref][1];
        weight2_cr[1] = wbp_weight[list_offset         ][0  ][ref][2];

        offsetBi_cr[0] = (wp_offset[list_offset + LIST_1][0  ][1] + wp_offset[list_offset         ][0  ][1] + 1) >> 1;
        offsetBi_cr[1] = (wp_offset[list_offset + LIST_1][0  ][2] + wp_offset[list_offset         ][0  ][2] + 1) >> 1;
      }
    }
  }
  else
  {
    weight1 = 1<<luma_log_weight_denom;
    weight2 = 1<<luma_log_weight_denom;
    offsetBi = 0;
    if ( ChromaMEEnable)
    {
      weight1_cr[0] = 1<<chroma_log_weight_denom;
      weight1_cr[1] = 1<<chroma_log_weight_denom;
      weight2_cr[0] = 1<<chroma_log_weight_denom;
      weight2_cr[1] = 1<<chroma_log_weight_denom;
      offsetBi_cr[0] = 0;
      offsetBi_cr[1] = 0;
    }
  }
}

/*!
 ************************************************************************
 * \brief
 *    Set motion vector predictor
 ************************************************************************
 */
void SetMotionVectorPredictor (Macroblock *currMB, 
                               short  pmv[2],
                               char   **refPic,
                               short  ***tmp_mv,
                               short  ref_frame,
                               int    list,
                               int    mb_x,
                               int    mb_y,
                               int    blockshape_x,
                               int    blockshape_y)
{
  int mv_a, mv_b, mv_c, pred_vec=0;
  int mvPredType, rFrameL, rFrameU, rFrameUR;
  int hv;

  PixelPos block_a, block_b, block_c, block_d;
  int *mb_size = img->mb_size[IS_LUMA];

  get4x4Neighbour(currMB, mb_x - 1,            mb_y    , mb_size, &block_a);
  get4x4Neighbour(currMB, mb_x,                mb_y - 1, mb_size, &block_b);
  get4x4Neighbour(currMB, mb_x + blockshape_x, mb_y - 1, mb_size, &block_c);
  get4x4Neighbour(currMB, mb_x - 1,            mb_y - 1, mb_size, &block_d);

  if (mb_y > 0)
  {
    if (mb_x < 8)  // first column of 8x8 blocks
    {
      if (mb_y == 8 )
      {
        if (blockshape_x == 16)      block_c.available  = 0;
      }
      else if (mb_x+blockshape_x == 8)
      {
          block_c.available = 0;
      }
    }
    else if (mb_x+blockshape_x == 16)
    {
      block_c.available = 0;
    }
  }

  if (!block_c.available)
  {
    block_c = block_d;
  }

  mvPredType = MVPRED_MEDIAN;

  if (!img->MbaffFrameFlag)
  {
    rFrameL    = block_a.available ? refPic[block_a.pos_y][block_a.pos_x] : -1;
    rFrameU    = block_b.available ? refPic[block_b.pos_y][block_b.pos_x] : -1;
    rFrameUR   = block_c.available ? refPic[block_c.pos_y][block_c.pos_x] : -1;
  }
  else
  {
    if (currMB->mb_field)
    {
      rFrameL  = block_a.available
        ? (img->mb_data[block_a.mb_addr].mb_field
        ? refPic[block_a.pos_y][block_a.pos_x]
        : refPic[block_a.pos_y][block_a.pos_x] * 2) : -1;
      rFrameU  = block_b.available
        ? (img->mb_data[block_b.mb_addr].mb_field
        ? refPic[block_b.pos_y][block_b.pos_x]
        : refPic[block_b.pos_y][block_b.pos_x] * 2) : -1;
      rFrameUR = block_c.available
        ? (img->mb_data[block_c.mb_addr].mb_field
        ? refPic[block_c.pos_y][block_c.pos_x]
        : refPic[block_c.pos_y][block_c.pos_x] * 2) : -1;
    }
    else
    {
      rFrameL = block_a.available
        ? (img->mb_data[block_a.mb_addr].mb_field
        ? refPic[block_a.pos_y][block_a.pos_x] >>1
        : refPic[block_a.pos_y][block_a.pos_x]) : -1;
      rFrameU  = block_b.available
        ? (img->mb_data[block_b.mb_addr].mb_field
        ? refPic[block_b.pos_y][block_b.pos_x] >>1
        : refPic[block_b.pos_y][block_b.pos_x]) : -1;
      rFrameUR = block_c.available
        ? (img->mb_data[block_c.mb_addr].mb_field
        ? refPic[block_c.pos_y][block_c.pos_x] >>1
        : refPic[block_c.pos_y][block_c.pos_x]) : -1;
    }
  }

  /* Prediction if only one of the neighbors uses the reference frame
  *  we are checking
  */
  if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)       
    mvPredType = MVPRED_L;
  else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)  
    mvPredType = MVPRED_U;
  else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)  
    mvPredType = MVPRED_UR;
  // Directional predictions
  if(blockshape_x == 8 && blockshape_y == 16)
  {
    if(mb_x == 0)
    {
      if(rFrameL == ref_frame)
        mvPredType = MVPRED_L;
    }
    else
    {
      if( rFrameUR == ref_frame)
        mvPredType = MVPRED_UR;
    }
  }
  else if(blockshape_x == 16 && blockshape_y == 8)
  {
    if(mb_y == 0)
    {
      if(rFrameU == ref_frame)
        mvPredType = MVPRED_U;
    }
    else
    {
      if(rFrameL == ref_frame)
        mvPredType = MVPRED_L;
    }
  }

  for (hv=0; hv < 2; hv++)
  {
    if (!img->MbaffFrameFlag || hv==0)
    {
      mv_a = block_a.available ? tmp_mv[block_a.pos_y][block_a.pos_x][hv] : 0;
      mv_b = block_b.available ? tmp_mv[block_b.pos_y][block_b.pos_x][hv] : 0;
      mv_c = block_c.available ? tmp_mv[block_c.pos_y][block_c.pos_x][hv] : 0;
    }
    else
    {
      if (currMB->mb_field)
      {
        mv_a = block_a.available  ? img->mb_data[block_a.mb_addr].mb_field
          ? tmp_mv[block_a.pos_y][block_a.pos_x][hv]
          : tmp_mv[block_a.pos_y][block_a.pos_x][hv] / 2
          : 0;
        mv_b = block_b.available  ? img->mb_data[block_b.mb_addr].mb_field

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -