rdopt.c

来自「the newest JM software by h.264 JVT offi」· C语言 代码 · 共 1,966 行 · 第 1/5 页

C
1,966
字号
/*!
 ***************************************************************************
 * \file rdopt.c
 *
 * \brief
 *    Rate-Distortion optimized mode decision
 *
 * \author
 *    - Heiko Schwarz              <hschwarz@hhi.de>
 *    - Valeri George              <george@hhi.de>
 *    - Lowell Winger              <lwinger@lsil.com>
 *    - Alexis Michael Tourapis    <alexismt@ieee.org>
 * \date
 *    12. April 2001
 **************************************************************************
 */

#include <math.h>
#include <limits.h>

#include "global.h"

#include "rdopt.h"
#include "q_around.h"
#include "rdopt_coding_state.h"
#include "memalloc.h"
#include "mb_access.h"
#include "elements.h"
#include "intrarefresh.h"
#include "image.h"
#include "transform8x8.h"
#include "cabac.h"
#include "biariencode.h"
#include "vlc.h"
#include "me_umhex.h"
#include "ratectl.h"            // head file for rate control
#include "mode_decision.h"
#include "rd_intra_jm.h"
#include "fmo.h"
#include "macroblock.h"
#include "symbol.h"
#include "q_offsets.h"
#include "conformance.h"
#include "errdo.h"
#include "mv-search.h"
#include "md_common.h"

#define FASTMODE 1
//#define RESET_STATE
static int diff[16];
static int diff4x4[64];
static int diff8x8[64];
RD_8x8DATA tr4x4, tr8x8;
imgpel ***rec8x8 = NULL;
imgpel ***rec4x4 = NULL;
imgpel ***rec4x4CbCr = NULL;
imgpel **pred = NULL;
imgpel **rec_mbY = NULL, ***rec_mb_cr = NULL;
static int **lrec_rec = NULL, ***lrec_rec_uv = NULL; // store the transf. and quantized coefficients for SP frames


int   ****cofAC  = NULL;        // [8x8block][4x4block][level/run][scan_pos]
int   ***cofDC   = NULL;                       // [yuv][level/run][scan_pos]
int   **cofAC4x4 = NULL, ****cofAC4x4intern = NULL; // [level/run][scan_pos]
int   cbp, cbp8x8, cnt_nonz_8x8;
int   cbp_blk8x8;
char  **l0_refframe, **l1_refframe;
short b8mode[4], b8pdir[4], b8bipred_me[4];

CSptr cs_mb=NULL, cs_b8=NULL, cs_cm=NULL, cs_ib8=NULL, cs_ib4=NULL;
int   best_c_imode;
int   best_i16offset;
short best_mode;


//mixed transform sizes definitions
int   luma_transform_size_8x8_flag;

short *****all_mv8x8 = NULL;       //[8x8_data/temp_data][LIST][block_x][block_y][MVx/MVy]

int   *****cofAC4x4CbCrintern = NULL;
int   *****cofAC8x8ts = NULL;        // [plane][8x8block][4x4block][level/run][scan_pos]
int   *****coefAC8x8 = NULL;
int   **cofAC4x4CbCr[2];


int64    cbp_blk8_8x8ts;
int      cbp8_8x8ts;
int      cost8_8x8ts;
int      cnt_nonz8_8x8ts;

// adaptive langrangian parameters
double mb16x16_cost;
double lambda_mf_factor;

void StoreMV8x8(int dir);
void RestoreMV8x8(int dir);
// end of mixed transform sizes definitions

char  b4_ipredmode[16], b4_intra_pred_modes[16];


void alloc_rd8x8data (RD_8x8DATA *rd_data)
{  
  get_mem2Dint(&rd_data->lrec, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem2Dpel(&rd_data->mpr8x8, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem3Dpel(&rd_data->mpr8x8CbCr, 2, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem2Dpel(&rd_data->rec_mbY8x8, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem3Dpel(&rd_data->rec_mb8x8_cr, 2, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
}

void free_rd8x8data (RD_8x8DATA *rd_data)
{
  free_mem3Dpel(rd_data->rec_mb8x8_cr);
  free_mem2Dpel(rd_data->rec_mbY8x8);
  free_mem3Dpel(rd_data->mpr8x8CbCr);
  free_mem2Dpel(rd_data->mpr8x8);  
  free_mem2Dint(rd_data->lrec);
}

/*!
 ************************************************************************
 * \brief
 *    delete structure for RD-optimized mode decision
 ************************************************************************
 */
void clear_rdopt (InputParameters *params)
{  
  free_mem_DCcoeff (cofDC);
  free_mem_ACcoeff (cofAC);
  free_mem_ACcoeff (cofAC4x4intern);
  free_mem_ACcoeff_new(coefAC8x8);

  if (params->Transform8x8Mode)
  {
    free_mem_ACcoeff_new(cofAC8x8ts);
  }
  //if (img->P444_joined)
  {

    free_mem_ACcoeff_new(cofAC4x4CbCrintern);
  }

  // Should create new functions for free/alloc of RD_8x8DATA
  free_rd8x8data(&tr4x4);
  free_rd8x8data(&tr8x8);

  free_mem5Dshort(all_mv8x8);

  free_mem3Dpel(rec4x4CbCr);
  free_mem3Dpel(rec4x4);
  free_mem3Dpel(rec8x8);
  free_mem2Dpel(pred);
  free_mem2Dpel(rec_mbY);
  free_mem3Dpel(rec_mb_cr);

  free_mem2Dint(lrec_rec);
  free_mem3Dint(lrec_rec_uv);
  free_mem2D((byte **) l0_refframe);  
  free_mem2D((byte **) l1_refframe);  

  // structure for saving the coding state
  delete_coding_state (cs_mb);
  delete_coding_state (cs_b8);
  delete_coding_state (cs_cm);
  delete_coding_state (cs_ib8);
  delete_coding_state (cs_ib4);
}


/*!
 ************************************************************************
 * \brief
 *    create structure for RD-optimized mode decision
 ************************************************************************
 */
void init_rdopt (InputParameters *params)
{
  rdopt = NULL;

  get_mem_DCcoeff (&cofDC);
  get_mem_ACcoeff (&cofAC);
  get_mem_ACcoeff (&cofAC4x4intern);
  cofAC4x4 = cofAC4x4intern[0][0];
  get_mem_ACcoeff_new(&coefAC8x8, 3);

  if (params->Transform8x8Mode)
  {
    get_mem_ACcoeff_new(&cofAC8x8ts, 3);
  }

  alloc_rd8x8data(&tr4x4);
  alloc_rd8x8data(&tr8x8);

  get_mem2Dpel(&pred, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem3Dpel(&rec8x8, 3, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8);
  get_mem3Dpel(&rec4x4, 3, BLOCK_SIZE, BLOCK_SIZE);
  get_mem3Dpel(&rec4x4CbCr, 2, BLOCK_SIZE, BLOCK_SIZE);
  get_mem2Dpel(&rec_mbY, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem3Dpel(&rec_mb_cr, 2, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem2Dint(&lrec_rec, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem3Dint(&lrec_rec_uv, 2, MB_BLOCK_SIZE, MB_BLOCK_SIZE);
  get_mem2D((byte ***) &l0_refframe, 4, 4);
  get_mem2D((byte ***) &l1_refframe, 4, 4);

  get_mem5Dshort(&all_mv8x8, 2, 2, 4, 4, 2);

  //if (img->P444_joined)
  {

    get_mem_ACcoeff_new(&cofAC4x4CbCrintern, 2);

    cofAC4x4CbCr[0] = cofAC4x4CbCrintern[0][0][0];
    cofAC4x4CbCr[1] = cofAC4x4CbCrintern[0][1][0];    
  }

  SetLagrangianMultipliers = params->rdopt == 0 ? SetLagrangianMultipliersOff : SetLagrangianMultipliersOn;

  switch (params->rdopt)
  {
  case 0:
    encode_one_macroblock = encode_one_macroblock_low;
    break;
  case 1:
  default:
    encode_one_macroblock = encode_one_macroblock_high;
    break;
  case 2:
    encode_one_macroblock = encode_one_macroblock_highfast;
    break;
  case 3:
    encode_one_macroblock = encode_one_macroblock_highloss;
    break;
  }
  
  // structure for saving the coding state
  cs_mb  = create_coding_state ();
  cs_b8  = create_coding_state ();
  cs_cm  = create_coding_state ();
  cs_ib8 = create_coding_state ();
  cs_ib4 = create_coding_state ();

  if (params->CtxAdptLagrangeMult == 1)
  {
    mb16x16_cost = CALM_MF_FACTOR_THRESHOLD;
    lambda_mf_factor = 1.0;
  }

  if (params->rdopt == 0)
  {
    Mode_Decision_for_8x8IntraBlocks = Mode_Decision_for_8x8IntraBlocks_JM_Low;
    Mode_Decision_for_4x4IntraBlocks = Mode_Decision_for_4x4IntraBlocks_JM_Low;
  }
  else
  {
    Mode_Decision_for_8x8IntraBlocks = Mode_Decision_for_8x8IntraBlocks_JM_High;
    Mode_Decision_for_4x4IntraBlocks = Mode_Decision_for_4x4IntraBlocks_JM_High;   
  }
  find_sad_16x16 = find_sad_16x16_JM;
  getDistortion = distortionSSE;

}

/*!
 *************************************************************************************
 * \brief
 *    Updates the pixel map that shows, which reference frames are reliable for
 *    each MB-area of the picture.
 *
 * \note
 *    The new values of the pixel_map are taken from the temporary buffer refresh_map
 *
 *************************************************************************************
 */
void UpdatePixelMap()
{
  int mx,my,y,x,i,j;
  if (img->type==I_SLICE)
  {
    memset(pixel_map, 1, img->height * img->width * sizeof(byte));
  }
  else
  {
    for (my=0; my<img->height >> 3; my++)
      for (mx=0; mx<img->width >> 3;  mx++)
      {
        j = my*8 + 8;
        i = mx*8 + 8;
        if (refresh_map[my][mx])
        {
          for (y=my*8; y<j; y++)
            memset(&pixel_map[y][mx*8], 1, 8 * sizeof(byte));
        }
        else
        {
          for (y=my*8; y<j; y++)
            for (x=mx*8; x<i; x++)
            {
              pixel_map[y][x] = imin(pixel_map[y][x] + 1, params->num_ref_frames+1);
            }
        }
      }
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Checks if a given reference frame is reliable for the current
 *    macroblock, given the motion vectors that the motion search has
 *    returned.
 *
 * \return
 *    If the return value is 1, the reference frame is reliable. If it
 *    is 0, then it is not reliable.
 *
 * \note
 *    A specific area in each reference frame is assumed to be unreliable
 *    if the same area has been intra-refreshed in a subsequent frame.
 *    The information about intra-refreshed areas is kept in the pixel_map.
 *
 *************************************************************************************
 */
int CheckReliabilityOfRef (int block, int list_idx, int ref, int mode)
{
  int y,x, block_y, block_x, dy, dx, y_pos, x_pos, yy, xx, pres_x, pres_y;
  int maxold_x  = img->width-1;
  int maxold_y  = img->height-1;
  int ref_frame = ref + 1;

  int by0 = (mode>=4?2*(block >> 1):mode==2?2*block:0);
  int by1 = by0 + (mode>=4||mode==2?2:4);
  int bx0 = (mode>=4?2*(block & 0x01):mode==3?2*block:0);
  int bx1 = bx0 + (mode>=4||mode==3?2:4);

  for (block_y=by0; block_y<by1; block_y++)
  {
    for (block_x=bx0; block_x<bx1; block_x++)
    {
      y_pos  = img->all_mv[list_idx][ref][mode][block_y][block_x][1];
      y_pos += (img->block_y + block_y) * BLOCK_SIZE * 4;
      x_pos  = img->all_mv[list_idx][ref][mode][block_y][block_x][0];
      x_pos += (img->block_x + block_x) * BLOCK_SIZE * 4;

      /* Here we specify which pixels of the reference frame influence
      the reference values and check their reliability. This is
      based on the function Get_Reference_Pixel */

      dy = y_pos & 3;
      dx = x_pos & 3;

      y_pos = (y_pos - dy) >> 2;
      x_pos = (x_pos - dx) >> 2;

      if (dy==0 && dx==0) //full-pel
      {
        for (y=y_pos ; y < y_pos + BLOCK_SIZE ; y++)
          for (x=x_pos ; x < x_pos + BLOCK_SIZE ; x++)
            if (pixel_map[iClip3(0,maxold_y,y)][iClip3(0,maxold_x,x)] < ref_frame)
              return 0;
      }
      else  /* other positions */
      {
        if (dy == 0)
        {
          for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
          {
            pres_y = iClip3(0, maxold_y, y);
            for (x = x_pos ; x < x_pos + BLOCK_SIZE ; x++)
            {
              for(xx = -2 ; xx < 4 ; xx++) 
              {
                pres_x = iClip3(0, maxold_x, x + xx);
                if (pixel_map[pres_y][pres_x] < ref_frame)
                  return 0;
              }
            }
          }
        }
        else if (dx == 0)
        {
          for (y = y_pos ; y < y_pos + BLOCK_SIZE ; y++)
            for (x=x_pos ; x < x_pos + BLOCK_SIZE ; x++)
            {
              pres_x = iClip3(0,maxold_x,x);
              for(yy=-2;yy<4;yy++) 
              {
                pres_y = iClip3(0,maxold_y, yy + y);
                if (pixel_map[pres_y][pres_x] < ref_frame)
                  return 0;
              }
            }
        }
        else if (dx == 2)

⌨️ 快捷键说明

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