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

📄 macroblock.c

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

/*!
 *************************************************************************************
 * \file macroblock.c
 *
 * \brief
 *    Process one macroblock
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *    - Inge Lille-Langoy               <inge.lille-langoy@telenor.com>
 *    - Rickard Sjoberg                 <rickard.sjoberg@era.ericsson.se>
 *    - Jani Lainema                    <jani.lainema@nokia.com>
 *    - Sebastian Purreiter             <sebastian.purreiter@mch.siemens.de>
 *    - Detlev Marpe                    <marpe@hhi.de>
 *    - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *    - Ragip Kurceren                  <ragip.kurceren@nokia.com>
 *    - Alexis Michael Tourapis         <alexismt@ieee.org>
 *************************************************************************************
 */

#include "contributors.h"

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

#include "global.h"
#include "enc_statistics.h"

#include "elements.h"
#include "macroblock.h"
#include "mc_prediction.h"
#include "refbuf.h"
#include "fmo.h"
#include "vlc.h"
#include "image.h"
#include "mb_access.h"
#include "ratectl.h"              // header file for rate control
#include "cabac.h"
#include "transform8x8.h"
#include "transform.h"
#include "me_fullsearch.h"
#include "me_fullfast.h"
#include "symbol.h"
#include "rdoq.h"
#include "mv-search.h"


#if TRACE
#define TRACE_SE(trace,str)  snprintf(trace,TRACESTRING_SIZE,str)
#else
#define TRACE_SE(trace,str)
#endif

const byte QP_SCALE_CR[52]=
{
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
  12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
  28,29,29,30,31,32,32,33,34,34,35,35,36,36,37,37,
  37,38,38,38,39,39,39,39
};

static const int block8x8_idx[3][4][4] = 
{
  { {0, 1, 0, 0},
  {2, 3, 0, 0},
  {0, 0, 0, 0},
  {0, 0, 0, 0},
  },
  { {0, 1, 0, 0},
  {0, 1, 0, 0},
  {2, 3, 0, 0},
  {2, 3, 0, 0},
  },
  { {0, 0, 1, 1},
  {0, 0, 1, 1},
  {2, 2, 3, 3},
  {2, 2, 3, 3}
  }
};

static int  slice_too_big(Slice *currSlice, int rlc_bits);

static int  writeChromaIntraPredMode (Macroblock* currMB);
static int  writeMotionInfo2NAL      (Macroblock* currMB);
static int  writeChromaCoeff         (Macroblock* currMB);
static int  writeCBPandDquant        (Macroblock* currMB);



static int diff  [16];
static int diff64[64];

const unsigned char subblk_offset_x[3][8][4] =
{
  {
    {0, 4, 0, 4},
    {0, 4, 0, 4},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0}, 
  },
  { 
    {0, 4, 0, 4},
    {0, 4, 0, 4},
    {0, 4, 0, 4},
    {0, 4, 0, 4},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0}, 
  },
  {
    {0, 4, 0, 4},
    {8,12, 8,12},
    {0, 4, 0, 4},
    {8,12, 8,12},
    {0, 4, 0, 4},
    {8,12, 8,12},
    {0, 4, 0, 4},
    {8,12, 8,12}  
  }
};

const unsigned char subblk_offset_y[3][8][4] =
{
  {
    {0, 0, 4, 4},
    {0, 0, 4, 4},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0}, 
  },
  { 
    {0, 0, 4, 4},
    {8, 8,12,12},
    {0, 0, 4, 4},
    {8, 8,12,12},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
    {0, 0, 0, 0},
  },
  { 
    {0, 0, 4, 4},
    {0, 0, 4, 4},
    {8, 8,12,12},
    {8, 8,12,12},
    {0, 0, 4, 4},
    {0, 0, 4, 4},
    {8, 8,12,12},
    {8, 8,12,12},
  }
};

extern ColocatedParams *Co_located;
extern ColocatedParams *Co_located_JV[MAX_PLANE];  //!< Co_located to be used during 4:4:4 independent mode encoding

 /*!
 ************************************************************************
 * \brief
 *    updates the coordinates for the next macroblock to be processed
 *
 * \param mb_addr
 *    macroblock address in scan order
 ************************************************************************
 */
void set_MB_parameters (int mb_addr)
{
  img->current_mb_nr = mb_addr;

  get_mb_block_pos(mb_addr, &img->mb_x, &img->mb_y);

  img->block_x = img->mb_x << 2;
  img->block_y = img->mb_y << 2;
  img->pix_x   = img->block_x << 2;
  img->pix_y   = img->block_y << 2;
  img->opix_x  = img->pix_x;

  if (img->MbaffFrameFlag)
  {
    if (img->mb_data[mb_addr].mb_field)
    {
      pCurImg    = (mb_addr & 0x01) ? img_org_bot[0]  : img_org_top[0];
      pImgOrg[0] = pCurImg;
      if ((img->yuv_format != YUV400) && !IS_INDEPENDENT(params))
      {
        if (mb_addr & 0x01)
        {
          pImgOrg[1] = img_org_bot[1];
          pImgOrg[2] = img_org_bot[2];
        }
        else
        {
          pImgOrg[1] = img_org_top[1];
          pImgOrg[2] = img_org_top[2];
        }
      }

      img->opix_y   = (img->mb_y >> 1 ) << 4;
      img->mb_data[mb_addr].list_offset = (mb_addr % 2) ? 4 : 2;
    }
    else
    {
      pCurImg    = img_org_frm[0];      
      pImgOrg[0] = img_org_frm[0];

      if ((img->yuv_format != YUV400) && !IS_INDEPENDENT(params))
      {
        pImgOrg[1] = img_org_frm[1];
        pImgOrg[2] = img_org_frm[2];
      }

      img->opix_y   = img->block_y << 2;
      img->mb_data[mb_addr].list_offset = 0;
    }
  }
  else
  {
    img->opix_y   = img->block_y << 2;
    img->mb_data[mb_addr].list_offset = 0;
  }

  if (img->yuv_format != YUV400)
  {
    img->pix_c_x = (img->mb_cr_size_x * img->pix_x) >> 4;
    img->pix_c_y = (img->mb_cr_size_y * img->pix_y) >> 4;

    img->opix_c_x = (img->mb_cr_size_x * img->opix_x) >> 4;
    img->opix_c_y = (img->mb_cr_size_y * img->opix_y) >> 4;
  }
  //  printf ("set_MB_parameters: mb %d,  mb_x %d,  mb_y %d\n", mb_addr, img->mb_x, img->mb_y);
}


/*!
 ************************************************************************
 * \brief
 *    updates the coordinates and statistics parameter for the
 *    next macroblock
 ************************************************************************
 */
void proceed2nextMacroblock(Macroblock *currMB)
{
#if TRACE
  int use_bitstream_backing = (params->slice_mode == FIXED_RATE || params->slice_mode == CALL_BACK);
#endif
  int *bitCount = currMB->bitcounter;
  int i;
  StatParameters *cur_stats = &enc_picture->stats;

  if (bitCount[BITS_TOTAL_MB] > img->max_bitCount)
    printf("Warning!!! Number of bits (%d) of macroblock_layer() data seems to exceed defined limit (%d).\n", bitCount[BITS_TOTAL_MB],img->max_bitCount);

  // Update the statistics
  cur_stats->bit_use_mb_type[img->type]      += bitCount[BITS_MB_MODE       ];
  cur_stats->tmp_bit_use_cbp[img->type]      += bitCount[BITS_CBP_MB        ];
  cur_stats->bit_use_coeffC[img->type]       += bitCount[BITS_COEFF_UV_MB   ];
  cur_stats->bit_use_coeff[0][img->type]     += bitCount[BITS_COEFF_Y_MB    ];
  cur_stats->bit_use_coeff[1][img->type]     += bitCount[BITS_COEFF_CB_MB   ]; 
  cur_stats->bit_use_coeff[2][img->type]     += bitCount[BITS_COEFF_CR_MB   ]; 
  cur_stats->bit_use_delta_quant[img->type]  += bitCount[BITS_DELTA_QUANT_MB];
  cur_stats->bit_use_stuffingBits[img->type] += bitCount[BITS_STUFFING      ];

  if (IS_INTRA(currMB))
  {
    ++cur_stats->intra_chroma_mode[currMB->c_ipred_mode];

    if ((currMB->cbp&15) != 0)
    {
      ++cur_stats->mode_use_transform[img->type][currMB->mb_type][currMB->luma_transform_size_8x8_flag];
    }
  }

  ++cur_stats->mode_use[img->type][currMB->mb_type];
  cur_stats->bit_use_mode[img->type][currMB->mb_type] += bitCount[BITS_INTER_MB];

  if (img->type != I_SLICE)
  {
    if (currMB->mb_type == P8x8)
    {
      for(i=0;i<4;i++)
      {
        if (currMB->b8mode[i] > 0)
          ++cur_stats->mode_use[img->type][currMB->b8mode[i]];
        else
          ++cur_stats->b8_mode_0_use[img->type][currMB->luma_transform_size_8x8_flag];

        if (currMB->b8mode[i]==4)
        {
          if ((currMB->luma_transform_size_8x8_flag && (currMB->cbp&15) != 0) || params->Transform8x8Mode == 2)
            ++cur_stats->mode_use_transform[img->type][4][1];
          else
            ++cur_stats->mode_use_transform[img->type][4][0];
        }
      }
    }
    else if (currMB->mb_type >= 0 && currMB->mb_type <=3 && ((currMB->cbp&15) != 0))
    {
      ++cur_stats->mode_use_transform[img->type][currMB->mb_type][currMB->luma_transform_size_8x8_flag];
    }
  }

  // Statistics
  cur_stats->quant[img->type] += currMB->qp;
  cur_stats->num_macroblocks[img->type]++;
}

void set_chroma_qp(ImageParameters *img, Macroblock* currMB)
{
  int i;
  for (i=0; i<2; i++)
  {
    currMB->qpc[i] = iClip3 ( -img->bitdepth_chroma_qp_scale, 51, currMB->qp + img->chroma_qp_offset[i] );
    currMB->qpc[i] = currMB->qpc[i] < 0 ? currMB->qpc[i] : QP_SCALE_CR[currMB->qpc[i]];
    currMB->qp_scaled[i + 1] = currMB->qpc[i] + img->bitdepth_chroma_qp_scale;
  }  
}

/*!
************************************************************************
* \brief
*    updates chroma QP according to luma QP and bit depth
************************************************************************
*/
void update_qp(ImageParameters *img, Macroblock *currMB)
{
  currMB->qp_scaled[0] = currMB->qp + img->bitdepth_luma_qp_scale;
  set_chroma_qp(img, currMB);

  select_dct(img, currMB);
}

/*!
 ************************************************************************
 * \brief
 *    resets info for the current macroblock
 *
 * \param currMB
 *    current macroblock
 * \param prev_mb
 *    previous macroblock address
 ************************************************************************
 */
void reset_macroblock(Macroblock *currMB, int prev_mb)
{
  int i,j,l;

  // Reset vectors and reference indices
  for (l=0; l<2; l++)
  {
    for (j=img->block_y; j < img->block_y + BLOCK_MULTIPLE; j++)
    {
      memset(&enc_picture->motion.ref_idx[l][j][img->block_x], -1, BLOCK_MULTIPLE * sizeof(char));
      memset(enc_picture->motion.mv [l][j][img->block_x], 0, 2 * BLOCK_MULTIPLE * sizeof(short));
      for (i=img->block_x; i < img->block_x + BLOCK_MULTIPLE; i++)
        enc_picture->motion.ref_pic_id[l][j][i]= -1;
    }
  }

  // Reset syntax element entries in MB struct
  currMB->mb_type      = 0;
  currMB->cbp_blk      = 0;
  currMB->cbp          = 0;  
  currMB->c_ipred_mode = DC_PRED_8;

  cmp_cbp[1] = cmp_cbp[2] = curr_cbp[0] = curr_cbp[1] = 0;

  memset(currMB->cbp_bits    , 0, 3 * sizeof(int64));
  memset(currMB->cbp_bits_8x8, 0, 3 * sizeof(int64));

  memset (currMB->mvd, 0, BLOCK_CONTEXT * sizeof(short));
  memset (currMB->intra_pred_modes, DC_PRED, MB_BLOCK_PARTITIONS * sizeof(char)); // changing this to char would allow us to use memset
  memset (currMB->intra_pred_modes8x8, DC_PRED, MB_BLOCK_PARTITIONS * sizeof(char));
  memset (currMB->bipred_me, 0, 4* sizeof(short));

  //initialize the whole MB as INTRA coded
  //Blocks are set to notINTRA in write_one_macroblock
  if (params->UseConstrainedIntraPred)
  {
    img->intra_block[img->current_mb_nr] = 1;
  }

  // Initialize bitcounters for this macroblock
  if(prev_mb < 0) // No slice header to account for
  {
    currMB->bitcounter[BITS_HEADER] = 0;
  }
  else if (currMB->slice_nr == img->mb_data[prev_mb].slice_nr) // current MB belongs to the
    // same slice as the last MB
  {
    currMB->bitcounter[BITS_HEADER] = 0;
  }

  currMB->bitcounter[BITS_MB_MODE       ] = 0;

⌨️ 快捷键说明

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