cabac.c

来自「JM 11.0 KTA 2.1 Source Code」· C语言 代码 · 共 1,962 行 · 第 1/5 页

C
1,962
字号

/*!
 *************************************************************************************
 * \file cabac.c
 *
 * \brief
 *    CABAC entropy coding routines
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *    - Detlev Marpe                    <marpe@hhi.de>
 **************************************************************************************
 */

#include <stdlib.h>
#include <assert.h>
#include <memory.h>
#include "global.h"

#include "cabac.h"
#include "image.h"
#include "mb_access.h"
#ifdef ADAPTIVE_FD_SD_CODING
#include "spatial_domain_coding.h"

extern int cabac_encoding;
#endif

#ifdef RDO_Q
estBitsCabacStruct estBitsCabac[NUM_BLOCK_TYPES];
int precalcUnaryLevelTab[128][MAX_PREC_COEFF];
extern int entropyBits[128];
#endif

static const int type2ctx_bcbp[] = { 0,  1,  2,  2,  3,  4,  5,  6,  5,  5}; // 7
#ifdef USE_INTRA_MDDT
static const int type2ctx_map [] = { 0,  1,  2,  3,  4,  5,  6,  7,  6,  6, 8}; // 9
static const int type2ctx_last[] = { 0,  1,  2,  3,  4,  5,  6,  7,  6,  6, 8}; // 9
static const int type2ctx_one [] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5, 7}; // 8
static const int type2ctx_abs [] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5, 7}; // 8
static const int max_c2       [] = { 4,  4,  4,  4,  4,  4,  3,  4,  3,  3, 4}; // 9
#else
static const int type2ctx_map [] = { 0,  1,  2,  3,  4,  5,  6,  7,  6,  6}; // 8
static const int type2ctx_last[] = { 0,  1,  2,  3,  4,  5,  6,  7,  6,  6}; // 8
static const int type2ctx_one [] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5}; // 7
static const int type2ctx_abs [] = { 0,  1,  2,  3,  3,  4,  5,  6,  5,  5}; // 7
static const int max_c2       [] = { 4,  4,  4,  4,  4,  4,  3,  4,  3,  3}; // 9
#endif

#define BIT_SET(x,n)  ((int)(((x)&((int64)1<<(n)))>>(n)))

int last_dquant = 0;

/***********************************************************************
 * L O C A L L Y   D E F I N E D   F U N C T I O N   P R O T O T Y P E S
 ***********************************************************************
 */


void unary_bin_encode(EncodingEnvironmentPtr eep_frame,
                      unsigned int symbol,
                      BiContextTypePtr ctx,
                      int ctx_offset);

void unary_bin_max_encode(EncodingEnvironmentPtr eep_frame,
                          unsigned int symbol,
                          BiContextTypePtr ctx,
                          int ctx_offset,
                          unsigned int max_symbol);

void unary_exp_golomb_level_encode( EncodingEnvironmentPtr eep_dp,
                                   unsigned int symbol,
                                   BiContextTypePtr ctx);

void unary_exp_golomb_mv_encode(EncodingEnvironmentPtr eep_dp,
                                unsigned int symbol,
                                BiContextTypePtr ctx,
                                unsigned int max_bin);


void cabac_new_slice(void)
{
  last_dquant=0;
}


/*!
 ************************************************************************
 * \brief
 *    Check for available neighbouring blocks
 *    and set pointers in current macroblock
 ************************************************************************
 */
void CheckAvailabilityOfNeighborsCABAC(void)
{
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
  PixelPos up, left;
  
  getNeighbour(img->current_mb_nr, -1,  0, 1, &left);
  getNeighbour(img->current_mb_nr,  0, -1, 1, &up);
  
  if (up.available)
    currMB->mb_available_up = &img->mb_data[up.mb_addr];
  else
    currMB->mb_available_up = NULL;
  
  if (left.available)
    currMB->mb_available_left = &img->mb_data[left.mb_addr];
  else
    currMB->mb_available_left = NULL;
}

/*!
 ************************************************************************
 * \brief
 *    Allocation of contexts models for the motion info
 *    used for arithmetic encoding
 ************************************************************************
 */
MotionInfoContexts* create_contexts_MotionInfo(void)
{
  MotionInfoContexts* enco_ctx;

  enco_ctx = (MotionInfoContexts*) calloc(1, sizeof(MotionInfoContexts) );
  if( enco_ctx == NULL )
    no_mem_exit("create_contexts_MotionInfo: enco_ctx");

  return enco_ctx;
}


/*!
 ************************************************************************
 * \brief
 *    Allocates of contexts models for the texture info
 *    used for arithmetic encoding
 ************************************************************************
 */
TextureInfoContexts* create_contexts_TextureInfo(void)
{
  TextureInfoContexts*  enco_ctx;

  enco_ctx = (TextureInfoContexts*) calloc(1, sizeof(TextureInfoContexts) );
  if( enco_ctx == NULL )
    no_mem_exit("create_contexts_TextureInfo: enco_ctx");

  return enco_ctx;
}




/*!
 ************************************************************************
 * \brief
 *    Frees the memory of the contexts models
 *    used for arithmetic encoding of the motion info.
 ************************************************************************
 */
void delete_contexts_MotionInfo(MotionInfoContexts *enco_ctx)
{
  if( enco_ctx == NULL )
    return;

  free( enco_ctx );

  return;
}

/*!
 ************************************************************************
 * \brief
 *    Frees the memory of the contexts models
 *    used for arithmetic encoding of the texture info.
 ************************************************************************
 */
void delete_contexts_TextureInfo(TextureInfoContexts *enco_ctx)
{
  if( enco_ctx == NULL )
    return;

  free( enco_ctx );

  return;
}


/*!
 **************************************************************************
 * \brief
 *    generates arithmetic code and passes the code to the buffer
 **************************************************************************
 */
int writeSyntaxElement_CABAC(SyntaxElement *se, DataPartition *this_dataPart)
{
  EncodingEnvironmentPtr eep_dp = &(this_dataPart->ee_cabac);
  int curr_len = arienco_bits_written(eep_dp);

  // perform the actual coding by calling the appropriate method
  se->writing(se, eep_dp);

  if(se->type != SE_HEADER)
    this_dataPart->bitstream->write_flag = 1;

  return (se->len = (arienco_bits_written(eep_dp) - curr_len));
}

/*!
 ***************************************************************************
 * \brief
 *    This function is used to arithmetically encode the field
 *    mode info of a given MB  in the case of mb-based frame/field decision
 ***************************************************************************
 */
void writeFieldModeInfo_CABAC(SyntaxElement *se, EncodingEnvironmentPtr eep_dp)
{
  int a,b,act_ctx;
  MotionInfoContexts *ctx         = (img->currentSlice)->mot_ctx;
  Macroblock         *currMB      = &img->mb_data[img->current_mb_nr];
  int                mb_field     = se->value1;
  
  a = currMB->mbAvailA ? img->mb_data[currMB->mbAddrA].mb_field : 0;
  b = currMB->mbAvailB ? img->mb_data[currMB->mbAddrB].mb_field : 0;
  
  act_ctx = a + b;
  
  biari_encode_symbol(eep_dp, (signed short) (mb_field != 0),&ctx->mb_aff_contexts[act_ctx]);
  
  se->context = act_ctx;
  
  return;
}

#ifdef ADAPTIVE_FD_SD_CODING
void write_adaptive_prederror_coding_flag_for_MB(SyntaxElement *se, EncodingEnvironmentPtr eep_dp)
{
  int a, b;
  int ctx = 0;
  int act_sym;

  Macroblock         *currMB      = &img->mb_data[img->current_mb_nr];

  b = (currMB->mb_available_up   == NULL) ? 0 : currMB->mb_available_up  ->SD_Coding_on_off;
  a = (currMB->mb_available_left == NULL) ? 0 : currMB->mb_available_left->SD_Coding_on_off;

  ctx         = a + 2 * b;
  act_sym     = se->value1;

  biari_encode_symbol (eep_dp, (short)act_sym, img->currentSlice->tex_ctx->MB_adaptive_SD_context+ctx);
}

void write_spatial_domain_coding_flag_for_4x4block (Macroblock* currMB, EncodingEnvironmentPtr eep_dp, int type, int FD_SD_bit)
{
  int y_ac        = (type==LUMA_16AC || type==LUMA_8x8 || type==LUMA_8x4 || type==LUMA_4x8 || type==LUMA_4x4);
  int y_dc        = (type==LUMA_16DC);
  int u_ac        = (type==CHROMA_AC && !img->is_v_block);
  int v_ac        = (type==CHROMA_AC &&  img->is_v_block);
  int chroma_dc   = (type==CHROMA_DC || type==CHROMA_DC_2x4 || type==CHROMA_DC_4x4);
  int u_dc        = (chroma_dc && !img->is_v_block);
  int v_dc        = (chroma_dc &&  img->is_v_block);
  int j           = (y_ac || u_ac || v_ac ? img->subblock_y : 0);
  int i           = (y_ac || u_ac || v_ac ? img->subblock_x : 0);
  int bit         = (y_dc ? 0 : y_ac ? 1 : u_dc ? 17 : v_dc ? 18 : u_ac ? 19 : 23);
  int default_bit = (img->is_intra_block ? 1 : 0);
  int upper_bit   = default_bit;
  int left_bit    = default_bit;
  int ctx;

  int bit_pos_a   = 0;
  int bit_pos_b   = 0;

  PixelPos block_a, block_b;

  if (y_ac || y_dc)
  {
    getLuma4x4Neighbour(img->current_mb_nr, i, j, -1,  0, &block_a);
    getLuma4x4Neighbour(img->current_mb_nr, i, j,  0, -1, &block_b);
    if (y_ac)
    {
      if (block_a.available)
        bit_pos_a = 4*block_a.y + block_a.x;
      if (block_b.available)
        bit_pos_b = 4*block_b.y + block_b.x;
    }
  }
  else
  {
    getChroma4x4Neighbour(img->current_mb_nr, i, j, -1,  0, &block_a);
    getChroma4x4Neighbour(img->current_mb_nr, i, j,  0, -1, &block_b);
    if (u_ac||v_ac)
    {
      if (block_a.available)
        bit_pos_a = 4*block_a.y + block_a.x;
      if (block_b.available)
        bit_pos_b = 4*block_b.y + block_b.x;
    }
  }

  bit = (y_dc ? 0 : y_ac ? 1+4*j+i : u_dc ? 17 : v_dc ? 18 : u_ac ? 19+4*j+i : 35+4*j+i);
  //--- set bits for current block ---
  if (FD_SD_bit)
  {
    if (type==LUMA_8x8)
    {
      currMB->FD_or_SD_bits   |= ((int64)1<< bit   );
      currMB->FD_or_SD_bits   |= ((int64)1<<(bit+1));
      currMB->FD_or_SD_bits   |= ((int64)1<<(bit+4));
      currMB->FD_or_SD_bits   |= ((int64)1<<(bit+5));
    }
    else if (type==LUMA_8x4)
    {
      currMB->FD_or_SD_bits   |= ((int64)1<< bit   );
      currMB->FD_or_SD_bits   |= ((int64)1<<(bit+1));
    }
    else if (type==LUMA_4x8)
    {
      currMB->FD_or_SD_bits   |= ((int64)1<< bit   );
      currMB->FD_or_SD_bits   |= ((int64)1<<(bit+4));
    }
    else
    {
      currMB->FD_or_SD_bits   |= ((int64)1<<bit);
    }
  }

  bit = (y_dc ? 0 : y_ac ? 1 : u_dc ? 17 : v_dc ? 18 : u_ac ? 19 : 35);
  if (type!=LUMA_8x8)
  {
    if (block_b.available)
    {
      if(img->mb_data[block_b.mb_addr].mb_type==IPCM)
        upper_bit=1;
      else
        upper_bit = BIT_SET(img->mb_data[block_b.mb_addr].FD_or_SD_bits,bit+bit_pos_b);
    }


    if (block_a.available)
    {
      if(img->mb_data[block_a.mb_addr].mb_type==IPCM)
        left_bit=1;
      else
        left_bit = BIT_SET(img->mb_data[block_a.mb_addr].FD_or_SD_bits,bit+bit_pos_a);
    }

    ctx = 2*upper_bit+left_bit;

    //===== encode symbol =====
    biari_encode_symbol (eep_dp, (short)FD_SD_bit, img->currentSlice->tex_ctx->bcbp_contexts_FD_SD+ctx);
  }
}


void write_spatial_domain_coding_flag_for_8x8block  (Macroblock* currMB, EncodingEnvironmentPtr eep_dp, int type, int FD_SD_bit, int writing_b8)
{
  int ctx=0;

  int upper_bit   = 0;
  int left_bit    = 0;

  if (writing_b8==0)
  {
    upper_bit = (currMB->mb_available_up   == NULL) ? 0 : (((currMB->mb_available_up  ->SD_or_FD_t8x8) & 4)==0?0:1);
    left_bit  = (currMB->mb_available_left == NULL) ? 0 : (((currMB->mb_available_left->SD_or_FD_t8x8) & 2)==0?0:1);
  }
  else if (writing_b8==1)
  {
    upper_bit = (currMB->mb_available_up   == NULL) ? 0 : (((currMB->mb_available_up  ->SD_or_FD_t8x8) & 8)==0?0:1);
    left_bit  =                                                              (((currMB->SD_or_FD_t8x8) & 1)==0?0:1);
  }
  else if (writing_b8==2)
  {
    upper_bit =                                                              (((currMB->SD_or_FD_t8x8) & 1)==0?0:1);
    left_bit  = (currMB->mb_available_left == NULL) ? 0 : (((currMB->mb_available_left->SD_or_FD_t8x8) & 8)==0?0:1);
  }
  else
  {
    upper_bit =                                                              (((currMB->SD_or_FD_t8x8) & 2)==0?0:1);
    left_bit  =                                                              (((currMB->SD_or_FD_t8x8) & 4)==0?0:1);
  }

  ctx=2*upper_bit+left_bit;

  //===== encode symbol =====
  biari_encode_symbol (eep_dp, (short)FD_SD_bit, img->currentSlice->tex_ctx->bcbp8_contexts_FD_SD+ctx);
}
#endif




/*!
***************************************************************************

⌨️ 快捷键说明

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