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

📄 rdopt.c

📁 本源码是H.26L标准的Visual C++源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2001, International Telecommunications Union, Geneva
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the user without any
* license fee or royalty on an "as is" basis. The ITU disclaims
* any and all warranties, whether express, implied, or
* statutory, including any implied warranties of merchantability
* or of fitness for a particular purpose.  In no event shall the
* contributor or the ITU be liable for any incidental, punitive, or
* consequential damages of any kind whatsoever arising from the
* use of these programs.
*
* This disclaimer of warranty extends to the user of these programs
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The ITU does not represent or warrant that the programs furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of ITU-T Recommendations, including
* shareware, may be subject to royalty fees to patent holders.
* Information regarding the ITU-T patent policy is available from
* the ITU Web site at http://www.itu.int.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY.
************************************************************************
*/

/*!
 ***************************************************************************
 * \file rdopt.c
 *
 * \brief
 *    Rate-Distortion optimized mode decision
 *
 * \author
 *    Heiko Schwarz <hschwarz@hhi.de>
 *
 * \date
 *    12. April 2001
 **************************************************************************
 */

#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include "rdopt.h"
#include "refbuf.h"

extern const byte PRED_IPRED[7][7][6];
extern       int  QP2QUANT  [32];

//=== static parameters ===
RDOpt  *rdopt     = NULL;


int    *forward_me_done[9];
int    *tot_for_sad[9];


/*!
 ************************************************************************
 * \brief
 *    delete structure for RD-optimized mode decision
 ************************************************************************
 */
void clear_rdopt ()
{
  int i;

  // rd-optimization structure
  if (rdopt != NULL)
  {
    free (rdopt);
    rdopt = NULL;

    for (i=0; i<9; i++)
    {
      free (forward_me_done[i]);
      free (tot_for_sad    [i]);
    }
  }

  // structure for saving the coding state
  clear_coding_state ();
}


/*!
 ************************************************************************
 * \brief
 *    create structure for RD-optimized mode decision
 ************************************************************************
 */
void
init_rdopt ()
{
  int i;

  if (!input->rdopt)
    return;

  clear_rdopt ();

  // rd-optimization structure
  if ((rdopt = (RDOpt*) calloc (1, sizeof(RDOpt))) == NULL)
  {
    no_mem_exit ("init_rdopt: rdopt");
  }

  for (i=0; i<9; i++)
  {
    if ((forward_me_done[i] = (int*)malloc (img->buf_cycle*sizeof(int))) == NULL) no_mem_exit ("init_rdopt: forward_me_done");
    if ((tot_for_sad    [i] = (int*)malloc (img->buf_cycle*sizeof(int))) == NULL) no_mem_exit ("init_rdopt: tot_for_sad");
  }


  // structure for saving the coding state
  init_coding_state ();
}



/*!
 ************************************************************************
 * \brief
 *    set Rate-Distortion cost of 4x4 Intra modes
 ************************************************************************
 */
void
RDCost_Intra4x4_Block (int block_x,
                       int block_y,
                       int ipmode)
{
  int             dummy, left_ipmode, upper_ipmode, curr_ipmode, x, y;
  int             i            = block_x >> 2;
  int             j            = block_y >> 2;
  int             pic_block_x  = (img->pix_x+block_x) / BLOCK_SIZE;
  int             pic_block_y  = (img->pix_y+block_y) / BLOCK_SIZE;
  int             even_block   = ((i & 1) == 1);
  Slice          *currSlice    =  img->currentSlice;
  Macroblock     *currMB       = &img->mb_data[img->current_mb_nr];
  SyntaxElement  *currSE       = &img->MB_SyntaxElements[currMB->currSEnr];
  int            *partMap      = assignSE2partition[input->partition_mode];
  DataPartition  *dataPart;


  //===== perform DCT, Q, IQ, IDCT =====
  dct_luma (block_x, block_y, &dummy);

  //===== get distortion (SSD) of 4x4 block =====
  for   (y=0; y < BLOCK_SIZE; y++)
    for (x=0; x < BLOCK_SIZE; x++)
    {
      dummy = imgY_org[img->pix_y+block_y+y][img->pix_x+block_x+x] - img->m7[x][y];
      rdopt->distortion_4x4[j][i][ipmode] += img->quad[abs(dummy)];
    }
  rdopt->rdcost_4x4[j][i][ipmode] = (double)rdopt->distortion_4x4[j][i][ipmode];
  if (rdopt->rdcost_4x4[j][i][ipmode] >= rdopt->min_rdcost_4x4[j][i])
    return;

  //===== store the coding state =====
  store_coding_state ();

  //===== get (estimate) rate for intra prediction mode =====
  //--- set or estimate the values of syntax element ---
  if (even_block)
    // EVEN BLOCK: the values the of syntax element can be set correctly
  {
    // value of last block
    upper_ipmode   =  img->ipredmode [pic_block_x  ][pic_block_y  ];
    left_ipmode    =  img->ipredmode [pic_block_x-1][pic_block_y+1];
    curr_ipmode    =  img->ipredmode [pic_block_x  ][pic_block_y+1];
    currSE->value1 =  PRED_IPRED [upper_ipmode+1][left_ipmode+1][curr_ipmode];
    // value of this block
    upper_ipmode   =  img->ipredmode [pic_block_x+1][pic_block_y  ];
    currSE->value2 =  PRED_IPRED [upper_ipmode+1][curr_ipmode+1][ipmode];
  }
  else
  /* ODD BLOCK:  the second value of the syntax element cannot be set, since
   *             it will be known only after the next step. For estimating
   *             the rate the corresponding prediction mode is set to zero
   *             (minimum rate). */
  {
    upper_ipmode   =  img->ipredmode [pic_block_x+1][pic_block_y  ];
    left_ipmode    =  img->ipredmode [pic_block_x  ][pic_block_y+1];
    currSE->value1 =  PRED_IPRED [upper_ipmode+1][left_ipmode+1][ipmode];
    currSE->value2 =  0; // value with maximum probability
  }
  //--- set function pointers for syntax element ---
  if (input->symbol_mode == UVLC)   currSE->mapping = intrapred_linfo;
  else                currSE->writing = writeIntraPredMode2Buffer_CABAC;
  currSE->type = SE_INTRAPREDMODE;
  //--- choose the appropriate data partition ---
  if (img->type != B_IMG)     dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
  else                        dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
  //--- get length of syntax element ---
  dataPart->writeSyntaxElement (currSE, dataPart);
  rdopt->rate_imode_4x4[j][i][ipmode] = currSE->len;
  rdopt->rdcost_4x4[j][i][ipmode] += rdopt->lambda_intra*(double)rdopt->rate_imode_4x4[j][i][ipmode];
  if (rdopt->rdcost_4x4[j][i][ipmode] >= rdopt->min_rdcost_4x4[j][i])
  {
    restore_coding_state ();
    return;
  }
  currSE++;
  currMB->currSEnr++;

  //===== get rate for luminance coefficients =====
  rdopt->rate_luma_4x4[j][i][ipmode] = writeMB_bits_for_4x4_luma (i, j, 0);
  rdopt->rdcost_4x4[j][i][ipmode] += rdopt->lambda_intra*(double)rdopt->rate_luma_4x4[j][i][ipmode];

  //===== restore the saved coding state =====
  restore_coding_state ();

  //===== update best mode =====
  if (rdopt->rdcost_4x4[j][i][ipmode] < rdopt->min_rdcost_4x4[j][i])
  {
    rdopt->best_mode_4x4 [j][i] = ipmode;
    rdopt->min_rdcost_4x4[j][i] = rdopt->rdcost_4x4[j][i][ipmode];
  }
}


/*!
 ************************************************************************
 * \brief
 *    Get best 4x4 Intra mode by rate-dist-based decision
 ************************************************************************
 */
int
RD_Intra4x4_Mode_Decision (int block_x,
                           int block_y)
{
  int  ipmode, i, j;
  int  index_y     = block_y >> 2;
  int  index_x     = block_x >> 2;
  int  pic_pix_y   = img->pix_y + block_y;
  int  pic_pix_x   = img->pix_x + block_x;
  int  pic_block_y = pic_pix_y / BLOCK_SIZE;
  int  pic_block_x = pic_pix_x / BLOCK_SIZE;

  typedef int (*WRITE_SE)(SyntaxElement*, struct datapartition*);
  WRITE_SE     *writeSE=0;
  int           symbol_mode;



  /*=== set symbol mode to UVLC (CABAC does not work correctly -> wrong coding order) ===*
   *=== and store the original symbol mode and function pointers                      ===*/
  symbol_mode = input->symbol_mode;
  if (input->symbol_mode != UVLC)
  {
    input->symbol_mode = UVLC;
    if ((writeSE = (WRITE_SE*) calloc (img->currentSlice->max_part_nr, sizeof (WRITE_SE))) == NULL)
    {
      no_mem_exit ("RD_Intra4x4_Mode_Decision: writeSE");
    }
    for (i=0; i<img->currentSlice->max_part_nr; i++)
    {
      writeSE[i] = img->currentSlice->partArr[i].writeSyntaxElement;
      img->currentSlice->partArr[i].writeSyntaxElement = writeSyntaxElement_UVLC;
    }
  }


  //=== LOOP OVER ALL 4x4 INTRA PREDICTION MODES ===
  rdopt->best_mode_4x4 [index_y][index_x] = -1;
  rdopt->min_rdcost_4x4[index_y][index_x] =  1e30;
  for (ipmode=0; ipmode < NO_INTRA_PMODE; ipmode++)
  {
    rdopt->rdcost_4x4    [index_y][index_x][ipmode] = -1;
    rdopt->distortion_4x4[index_y][index_x][ipmode] =  0;
    rdopt->rate_imode_4x4[index_y][index_x][ipmode] =  0;
    rdopt->rate_luma_4x4 [index_y][index_x][ipmode] =  0;

    // Horizontal pred from Y neighbour pix , vertical use X pix, diagonal needs both
    if (ipmode==DC_PRED || ipmode==HOR_PRED || img->ipredmode[pic_block_x+1][pic_block_y] >= 0)
      // DC or vert pred or hor edge
    {
      if (ipmode==DC_PRED || ipmode==VERT_PRED || img->ipredmode[pic_block_x][pic_block_y+1] >= 0)
        // DC or hor pred or vert edge
      {
        // find diff
        for   (j=0; j < BLOCK_SIZE; j++)
          for (i=0; i < BLOCK_SIZE; i++)
            img->m7[i][j] = imgY_org[pic_pix_y+j][pic_pix_x+i] - img->mprr[ipmode][j][i];
          // copy intra prediction block
          for   (j=0; j < BLOCK_SIZE; j++)
            for (i=0; i < BLOCK_SIZE; i++)
              img->mpr[i+block_x][j+block_y] = img->mprr[ipmode][j][i];
          // get lagrangian cost
          RDCost_Intra4x4_Block (block_x, block_y, ipmode);
      }
    }
  }

  //=== restore the original symbol mode and function pointers ===
  if (symbol_mode != UVLC)
  {
    input->symbol_mode = symbol_mode;
    for (i=0; i<img->currentSlice->max_part_nr; i++)
    {
      img->currentSlice->partArr[i].writeSyntaxElement = writeSE[i];
    }
    free (writeSE);
  }

  return rdopt->best_mode_4x4[index_y][index_x];
}


/*!
 ************************************************************************
 * \brief
 *    Rate-Distortion opt. mode decision for 4x4 intra blocks
 ************************************************************************
 */
void
Intra4x4_Mode_Decision ()
{
  int i,j;
  int block_x, block_y;
  int best_ipmode;
  int coeff_cost; // not used
  int pic_pix_y,pic_pix_x,pic_block_y,pic_block_x;
  int last_ipred=0;           // keeps last chosen intra prediction mode for 4x4 intra pred
  int nonzero;                          // keep track of nonzero coefficients
  int cbp_mask;
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];

  // start making 4x4 intra prediction
  currMB->cbp=0;
  img->mb_data[img->current_mb_nr].intraOrInter = INTRA_MB_4x4;

  for(block_y = 0 ; block_y < MB_BLOCK_SIZE ; block_y += BLOCK_MULTIPLE)
  {
    pic_pix_y=img->pix_y+block_y;
    pic_block_y=pic_pix_y/BLOCK_SIZE;

    for(block_x = 0 ; block_x < MB_BLOCK_SIZE  ; block_x += BLOCK_MULTIPLE)
    {
      cbp_mask=(1<<(2*(block_y/8)+block_x/8));
      pic_pix_x=img->pix_x+block_x;
      pic_block_x=pic_pix_x/BLOCK_SIZE;

      /*
      intrapred_luma() makes and returns 4x4 blocks with all 5 intra prediction modes.
      Notice that some modes are not possible at frame edges.
      */
      intrapred_luma (pic_pix_x,pic_pix_y);

      //=== rate-constrained mode decision ===
      best_ipmode = RD_Intra4x4_Mode_Decision (block_x, block_y);

      img->ipredmode[pic_block_x+1][pic_block_y+1]=best_ipmode;

      if ((pic_block_x & 1) == 1) // just even blocks, two and two predmodes are sent together
      {
        currMB->intra_pred_modes[block_x/4+block_y]=PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][best_ipmode];
        currMB->intra_pred_modes[block_x/4-1+block_y]=last_ipred;
      }
      last_ipred=PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][best_ipmode];

      //  Make difference from prediction to be transformed

⌨️ 快捷键说明

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