h.264 scanning process for transform coefficients

宏塊在通過變換、量化後,獲得大小爲4x4或者8x8的矩陣,矩陣中的數據被稱爲transform coefficient levels。這些level在後面會被用於熵編碼,所以咱們須要把矩陣按照必定順序進行掃描,獲得數字序列。html

 

掃描順序在幀與場會有所不一樣ide

4x4塊矩陣的掃描順序以下編碼

image               image

Zig-zag scan(Frame)                          Field scan           3d

 

8x8塊矩陣的掃描順序以下orm

image            image

 

Zig-zag scan(Frame)                                  Field scan            htm

 

在實際的代碼處理上(JM),對變換系數的掃描過程是包含在量化過程當中的,由於對矩陣內的元素的量化也是逐個進行的,所以就能夠按照對變換系數掃描的順序取出矩陣內的元素進行量化,後續就能直接對這些transform coefficient level序列進行熵編碼。blog

int quant_4x4_normal(Macroblock *currMB, int **tblock, struct quant_methods *q_method)
{ 
  VideoParameters *p_Vid = currMB->p_Vid;
  QuantParameters *p_Quant = p_Vid->p_Quant;
  Slice *currSlice = currMB->p_Slice;
  Boolean is_cavlc = (Boolean) (currSlice->symbol_mode == CAVLC);
  
  int   block_x = q_method->block_x;
  int  qp = q_method->qp;
  int*  ACL = &q_method->ACLevel[0];
  int*  ACR = &q_method->ACRun[0];  
  LevelQuantParams **q_params_4x4 = q_method->q_params;
  const byte (*pos_scan)[2] = q_method->pos_scan;
  const byte *c_cost = q_method->c_cost;
  int *coeff_cost = q_method->coeff_cost;
  
  
  LevelQuantParams *q_params = NULL;
  int i,j, coeff_ctr;
  
  int *m7;
  int scaled_coeff;
  
  int   level, run = 0;
  int   nonzero = FALSE;
  int   qp_per = p_Quant->qp_per_matrix[qp];
  int   q_bits = Q_BITS + qp_per;
  const byte *p_scan = &pos_scan[0][0];

  // Quantization
  // 4x4 block matrix has 16 coefficients
  for (coeff_ctr = 0; coeff_ctr < 16; ++coeff_ctr)
  {
    //scanning positions (Zig-zag scan or Field scan)
    i = *p_scan++;  // horizontal position
    j = *p_scan++;  // vertical position
    
    //block_x,block_y here is the position of a block on a Macroblock with the unit of pixel
    m7 = &tblock[j][block_x + i];

    if (*m7 != 0)
    {
      q_params = &q_params_4x4[j][i];
      scaled_coeff = iabs (*m7) * q_params->ScaleComp;
      level = (scaled_coeff + q_params->OffsetComp) >> q_bits;

      if (level != 0)
      {
        if (is_cavlc)
          level = imin(level, CAVLC_LEVEL_LIMIT);

        *coeff_cost += (level > 1) ? MAX_VALUE : c_cost[run];

        level  = isignab(level, *m7);
        *m7     = rshift_rnd_sf(((level * q_params->InvScaleComp) << qp_per), 4);
        // inverse scale can be alternative performed as follows to ensure 16bit
        // arithmetic is satisfied.
        // *m7 = (qp_per<4) ? rshift_rnd_sf((level*q_params->InvScaleComp),4-qp_per) : (level*q_params->InvScaleComp)<<(qp_per-4);
        *ACL++ = level;
        *ACR++ = run;
        // reset zero level counter
        run    = 0;
        nonzero = TRUE;
      }
      else
      {
        *m7 = 0;
        ++run;
      }
    }
    else
    {
      ++run;
    }
  }

  *ACL = 0;

  return nonzero;
}
相關文章
相關標籤/搜索