Intra-prediction(2)之I_16x16

7 篇文章 3 订阅
2 篇文章 0 订阅

预处理

16x16布局

  • 当不存在H时

将H中的16个像素全部设值为dc_pred_value,即128

  if (*up_available)
  {
    memcpy(&PredPel[1], &img_enc[pix_b.pos_y][pix_b.pos_x], MB_BLOCK_SIZE * sizeof(imgpel));
  }
  else
  {
    for (i = 1; i < 17; ++i)
      PredPel[i] = (imgpel) p_Vid->dc_pred_value;
  }
  • 当不存在V时

将V中的16个像素全部设值为dc_pred_value,即128

  if (*left_available)
  {
    int pos_y = pix_a.pos_y;
    int pos_x = pix_a.pos_x;

    for (i = 1; i < MB_BLOCK_SIZE + 1; ++i)
      PredPel[i + 16] = img_enc[pos_y++][pos_x];
  }
  else
  {
    for (i = 17; i < 33; ++i)
      PredPel[i] = (imgpel) p_Vid->dc_pred_value;
  }
  • 当H和V都不存在时

设置左上角的像素点为dc_pred_value,即128

  if (*all_available)
  {
    PredPel[0] = img_enc[pix_d.pos_y][pix_d.pos_x];
  }
  else
  {
    PredPel[0] = p_Vid->dc_pred_value;
  }
关于dc_pred_value

dc_pred_value的值与图像的位深有关:dc_pred_value = 2 b i t d e p t h − 1 =2^{bitdepth-1} =2bitdepth1,一般的,当 b i t d e p t h = 8 bitdepth=8 bitdepth=8时,有dc_pred_value=128

  cps->dc_pred_value_comp[0]    =  (uint32) (1<<(cps->bitdepth_luma - 1));

四种模式

四种模式分别为
mode0 vertical
mode1 horizontal
mode2 DC
mode3 plane

enum {
  VERT_PRED_16   = 0,
  HOR_PRED_16    = 1,
  DC_PRED_16     = 2,
  PLANE_16       = 3
} I16x16PredModes;

mode0 vertical

在这里插入图片描述
将H中的16个像素向下复制即可

#define MB_BLOCK_SIZE         16
static inline void get_i16x16_vertical(imgpel **cur_pred, imgpel *PredPel)
{
  int j;
  for (j = 0; j < MB_BLOCK_SIZE; j++)
    memcpy(cur_pred[j], &PredPel[1], MB_BLOCK_SIZE * sizeof(imgpel));
}

mode1 horizontal

在这里插入图片描述
将V中的16个像素向右复制即可

#define MB_BLOCK_SIZE         16
static inline void get_i16x16_horizontal(imgpel **cur_pred, imgpel *PredPel)
{
  int i, j;
  imgpel *prediction = &PredPel[16];

  for (j = 0; j < MB_BLOCK_SIZE; j++)
  {  
    prediction++;
    for (i = 0; i < MB_BLOCK_SIZE; i++)
    {
      cur_pred[j][i]  = *prediction;
    }    
  }
}

mode2 DC

在这里插入图片描述
同I_4x4一样:
若H和V都有,则mean(H+V)
若只有H,则mean(H)
若只有V,则mean(V)
若H和V都没,则mean = 128

#define MB_BLOCK_SIZE         16
#define MB_BLOCK_SHIFT         4
static inline void get_i16x16_dc(imgpel **cur_pred, imgpel *PredPel, int left_available, int up_available)
{
  int i, j, s0 = 0, s1 = 0, s2 = 0;

  if (up_available)
  {
    for (i = 1; i < MB_BLOCK_SIZE + 1; ++i)
      s1 += PredPel[i];
  }

  if (left_available)
  {
    for (i = 17; i < 33; ++i)
      s2 += PredPel[i];    // sum vert pix
  }

  if (up_available)
  {
    s0 = left_available
      ? rshift_rnd_sf((s1 + s2),(MB_BLOCK_SHIFT + 1)) // all edge
      : rshift_rnd_sf(s1, MB_BLOCK_SHIFT);          // left edge
  }
  else
  {
    s0 = left_available
      ? rshift_rnd_sf(s2, MB_BLOCK_SHIFT)           // upper edge
      : PredPel[1];                              // top left corner, nothing to predict from;预处理中PredPel[1] = dc_pred_value
  }

  for (j = 0; j < MB_BLOCK_SIZE; j++)
  {
    for (i = 0; i < MB_BLOCK_SIZE; i++)
      cur_pred[j][i] = (imgpel) s0;    
  }
}

mode3 plane

在这里插入图片描述
根据源码分析有如下公式(意义尚不明确,欢迎指点)
H = ∑ x ′ = 0 7 ( x ′ + 1 ) ∗ ( p [ 8 + x ′ , − 1 ] − p [ 6 − x ′ , − 1 ] ) V = ∑ y ′ = 0 7 ( y ′ + 1 ) ∗ ( p [ − 1 , 8 + y ′ ] − p [ − 1 , 6 − y ′ ] ) a = 16 ∗ ( p [ − 1 , 15 ] + p [ 15 , − 1 ] ) b = ( 5 ∗ H + 32 ) &gt; &gt; 6 c = ( 5 ∗ V + 32 ) &gt; &gt; 6 p r e d L [ x , y ] = C l i p 1 ( ( a + b ∗ ( x − 7 ) + c ∗ ( y − 7 ) + 16 ) ) H=\sum_{x&#x27;=0}^{7} (x&#x27;+1)*(p[8+x&#x27;,-1]-p[6-x&#x27;,-1])\\ V=\sum_{y&#x27;=0}^{7} (y&#x27;+1)*(p[-1,8+y&#x27;]-p[-1,6-y&#x27;])\\ a=16*(p[-1,15]+p[15,-1])\\ b=(5*H+32)&gt;&gt;6\\ c=(5*V+32)&gt;&gt;6\\ pred_L[x,y]=Clip1( (a+b*(x-7)+c*(y-7)+16) ) H=x=07(x+1)(p[8+x,1]p[6x,1])V=y=07(y+1)(p[1,8+y]p[1,6y])a=16(p[1,15]+p[15,1])b=(5H+32)>>6c=(5V+32)>>6predL[x,y]=Clip1((a+b(x7)+c(y7)+16))

static inline void get_i16x16_plane(imgpel **cur_pred, imgpel *PredPel, int max_imgpel_value)
{
  int i, j;
  // plane prediction
  int ih=0, iv=0;
  int ib, ic, iaa;
  imgpel *t_pred = &PredPel[25];
  imgpel *u_pred = &PredPel[8];
  imgpel *b_pred = &PredPel[23];

  for (i = 1; i < 8;++i)
  {
    ih += i*(*(u_pred + i) - *(u_pred - i));
    iv += i*(*t_pred++ - *b_pred--);
  }
  ih += 8 * (*(u_pred + 8) - PredPel[0]);
  iv += 8 * (*t_pred++ - PredPel[0]);

  ib = (5 * ih + 32) >> 6;
  ic = (5 * iv + 32) >> 6;

  iaa=16 * (PredPel[16] + PredPel[32]);

  for (j=0;j< MB_BLOCK_SIZE;++j)
  {
    for (i=0;i< MB_BLOCK_SIZE;++i)
    {
      //iClip1(max , a)将a限定在[0,max]范围中,这里则是限定在[0,255]中,保证像素值有意义   
      cur_pred[j][i]= (imgpel) iClip1( max_imgpel_value, rshift_rnd_sf((iaa + (i - 7) * ib + (j - 7) * ic), 5));// store plane prediction
    } 
  }
}

模式的选择

遍历4种预测模式vertical horizontal DC plane,计算各种模式下的开销(SAD SSE SATD),选择开销最小的模式。

find_best_mode_I16x16_MB
find_sad_16x16
set_intrapred_16x16
get_intrapred_16x16
distI16x16
distI16x16_sad
distI16x16_sse
distI16x16_satd
  • find_best_mode_I16x16_MB用来找到最佳的16x16模式,并返回该最佳模式下的开销
//rd_intra_jm.c
int find_best_mode_I16x16_MB (Macroblock *currMB, int lambda,  distblk min_cost)
{
  Slice *currSlice = currMB->p_Slice;
  currMB->luma_transform_size_8x8_flag = FALSE;
  return (int) currSlice->find_sad_16x16 (currMB);
}
  • find_sad_16x16函数指针,该指针指向函数find_sad_16x16_JM,计算最优模式并返回最优模式的开销
distblk find_sad_16x16_JM(Macroblock *currMB)
{
  Slice *currSlice = currMB->p_Slice;	//得到当前MB的slice
  VideoParameters *p_Vid = currMB->p_Vid;	//得到video参数
  InputParameters *p_Inp = currMB->p_Inp;	//得到input参数
  distblk current_intra_sad_2, best_intra_sad2 = DISTBLK_MAX;	//初始化当前intra模式和最优intra模式的sad为最大值
  int k;
  imgpel  ***curr_mpr_16x16 = currSlice->mpr_16x16[0];

  int up_avail, left_avail, left_up_avail;

  currMB->i16mode = DC_PRED_16;	//暂设当前MB为DC
  
  currSlice->set_intrapred_16x16(currMB, PLANE_Y, &left_avail, &up_avail, &left_up_avail);	//对Y进行边缘像素预处理
  // For speed purposes, we should just unify all planes
  if (currSlice->P444_joined)	//若是YUV444格式
  {
    currSlice->set_intrapred_16x16(currMB, PLANE_U, &left_avail, &up_avail, &left_up_avail);	//对U进行边缘像素预处理
    currSlice->set_intrapred_16x16(currMB, PLANE_V, &left_avail, &up_avail, &left_up_avail);	//对V进行边缘像素预处理
  }

  for (k = VERT_PRED_16; k <= PLANE_16; k++)	//遍历4种模式 vertical	horizontal	DC	plane
  {
    if (p_Inp->IntraDisableInterOnly == 0 || (currSlice->slice_type != I_SLICE && currSlice->slice_type != SI_SLICE) )
    {
      if (p_Inp->Intra16x16ParDisable && (k == VERT_PRED_16||k == HOR_PRED_16))
        continue;

      if (p_Inp->Intra16x16PlaneDisable && k == PLANE_16)
        continue;
    }
    //check if there are neighbours to predict from
    if (!((k == VERT_PRED_16 && !up_avail) || (k == HOR_PRED_16 && !left_avail) || (k == PLANE_16 && (!left_avail || !up_avail || !left_up_avail))))
    {	//若当前模式为vertical且up像素不可用	或	当前模式horizontal且left像素不可用	或	当前模式plane且left/up/left_up像素存在不可用
      get_intrapred_16x16(currMB, PLANE_Y, k, left_avail, up_avail);	//对Y使用当前模式k
      current_intra_sad_2 = currSlice->distI16x16(currMB, p_Vid->pCurImg, curr_mpr_16x16[k], best_intra_sad2);	//计算该模式下的开销
      if (currSlice->P444_joined)
      {
        get_intrapred_16x16(currMB, PLANE_U, k, left_avail, up_avail);
        current_intra_sad_2 += currSlice->distI16x16(currMB, p_Vid->pImgOrg[1], currSlice->mpr_16x16[1][k], best_intra_sad2);
        get_intrapred_16x16(currMB, PLANE_V, k, left_avail, up_avail);
        current_intra_sad_2 += currSlice->distI16x16(currMB, p_Vid->pImgOrg[2], currSlice->mpr_16x16[2][k], best_intra_sad2);
      }

      if (current_intra_sad_2 < best_intra_sad2)	//若当前模式的开销小于最优模式的开销
      {
		//更新最优模式
        best_intra_sad2 = current_intra_sad_2;
        currMB->i16mode = (char) k; // update best intra mode
      }
    }    
  }

  return best_intra_sad2;	//返回最优模式的开销
}
  • set_intrapred_16x16为intraprediction预处理
  • get_intrapred_16x16为MB应用相应的mode
void get_intrapred_16x16(Macroblock *currMB, ColorPlane pl, int i16x16_mode, int left_available, int up_available)
{
  imgpel        *PredPel = currMB->intra16x16_pred[pl];  // array of predictor pels
  imgpel ***curr_mpr_16x16 = currMB->p_Slice->mpr_16x16[pl];

  switch (i16x16_mode)
  {
  case VERT_PRED_16 :    
    get_i16x16_vertical(curr_mpr_16x16[VERT_PRED_16], PredPel);
    break;
  case HOR_PRED_16 :
    get_i16x16_horizontal(curr_mpr_16x16[HOR_PRED_16], PredPel);
    break;
  case DC_PRED_16 :
    get_i16x16_dc(curr_mpr_16x16[DC_PRED_16], PredPel, left_available, up_available);
    break;
  case PLANE_16 :
    get_i16x16_plane(curr_mpr_16x16[PLANE_16], PredPel, currMB->p_Vid->max_imgpel_value);
    break;
  default:
    printf("invalid prediction mode \n");
    break;
  }
}

代码参考:JM19.0
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值