帧内预测模式提取

来源:互联网 发布:杭州声讯网络 编辑:程序博客网 时间:2024/05/01 20:00

if (input->rdopt)
    {
      int mb_available_up;
      int mb_available_left;
      int mb_available_up_left;
     
      min_rdcost = max_rdcost;
     
      // precompute all new chroma intra prediction modes
   //++ 对色度进行帧内预测
      IntraChromaPrediction8x8(&mb_available_up, &mb_available_left, &mb_available_up_left);
     
   //++ 分别在四种色度模式下进行 RDO 计算,如果是 inter 模式,因为色度预测模式与 SSD 计算
   //++ 无关,因此只需要计算一次(利用 currMB->c_ipred_mode == DC_PRED_8 条件限制来实现)
      for (currMB->c_ipred_mode=DC_PRED_8; currMB->c_ipred_mode<=PLANE_8; currMB->c_ipred_mode++)
      {
       
        // bypass if c_ipred_mode is not allowed
        if ((currMB->c_ipred_mode==VERT_PRED_8 && !mb_available_up) ||
          (currMB->c_ipred_mode==HOR_PRED_8 && !mb_available_left) ||
          (currMB->c_ipred_mode==PLANE_8 && (!mb_available_left || !mb_available_up || !mb_available_up_left)))
          continue;
       
       
        //===== GET BEST MACROBLOCK MODE =====
        for (ctr16x16=0, index=0; index<7; index++)
        {
          mode = mb_mode_table[index];
         
          //--- for INTER16x16 check all prediction directions ---
          if (mode==1 && img->type==B_SLICE)
          {
            best8x8pdir[1][0] = best8x8pdir[1][1] = best8x8pdir[1][2] = best8x8pdir[1][3] = ctr16x16;
            if (ctr16x16 < 2) index--;
            ctr16x16++;
          }
         
          img->NoResidueDirect = 0;
         
          if (valid[mode])
          {
            // bypass if c_ipred_mode not used
    //++ 设置当前宏块类型以及其中每个8*8块的分割方式和预测方向,每个4*4块的参考帧索引
    //++ 该函数在下面的 RDCost_for_macroblocks 函数内再次调用,进行了重复操作
            SetModesAndRefframeForBlocks (mode);
            if (currMB->c_ipred_mode == DC_PRED_8 || //++ 利用这个条件限制来实现 inter 模式时只计算一次 RDO
              (IS_INTRA(currMB) ))
            {
              if (RDCost_for_macroblocks (lambda_mode, mode, &min_rdcost)) //++ 帧内模式时亮度存在重复计算情况:因为色度预测模式与亮度预测模式无关,所以在该色度模
              {                 //++ 式循环中每次计算得到的 intra16*16 和 intra4*4 宏块类型的最佳亮度模式都是完全相同的
                //Rate control
                if(mode == P8x8)
                {
                  for (i=0; i<16; i++)
                    for(j=0; j<16; j++)
                      diffy[j][i] = imgY_org[img->opix_y+j][img->opix_x+i] - mpr8x8[j][i];
                }else
                {
                  for (i=0; i<16; i++)
                    for(j=0; j<16; j++)
                      diffy[j][i] = imgY_org[img->opix_y+j][img->opix_x+i] - pred[j][i];
                }
               
                store_macroblock_parameters (mode);
              }
            }
          }
          if (valid[0] && bframe && mode == 0 && currMB->cbp && (currMB->cbp&15) != 15) //g050
          {
            img->NoResidueDirect = 1;
            if (RDCost_for_macroblocks (lambda_mode, mode, &min_rdcost))
            {
              //Rate control
              for (i=0; i<16; i++)
                for(j=0; j<16; j++)
                  diffy[j][i] = imgY_org[img->opix_y+j][img->opix_x+i] - pred[j][i];
                store_macroblock_parameters (mode);
            }
          }
        }
      }
    }
    else
    {
      if (valid[0] && bframe) // check DIRECT MODE
      {
        cost = (have_direct?cost_direct:Get_Direct_CostMB (lambda_mode));
        cost -= (int)floor(16*lambda_motion+0.4999);
        if (cost <= min_cost)
        {
          //Rate control
          for (i=0; i<16; i++)
            for(j=0; j<16; j++)
              diffy[j][i] = imgY_org[img->pix_y+j][img->pix_x+i]-img->mpr[i][j];
           
            min_cost = cost;
            best_mode = 0;
        }
      }
      if (valid[I4MB]) // check INTRA4x4
      {
        currMB->cbp = Mode_Decision_for_Intra4x4Macroblock (lambda_mode, &cost); //++ 计算当前宏块采用intra4*4编码时的代价和CBP
        if (cost <= min_cost)
        {
          //Rate control
          for (i=0; i<16; i++)
            for(j=0; j<16; j++)
              diffy[j][i] = imgY_org[img->pix_y+j][img->pix_x+i]-img->mpr[i][j]; //++ 保存采用intra4*4编码时最佳模式的残差块
           
            min_cost = cost;
            best_mode = I4MB;
        }
      }
      if (valid[I16MB]) // check INTRA16x16
      {
        intrapred_luma_16x16 (); //++ 分别计算当前宏块在4种intra16*16帧内预测模式下的预测块
        cost = find_sad_16x16 (&i16mode); //++ 计算intra16*16类型的代价(以SATD作为判断标准,因为该段代码是不采用RDO的处理过程)
        if (cost < min_cost) //++ 如果采用intra16*16类型编码的代价小于采用intra4*4类型编码的代价,则对当前宏块采用intra16*16类型编码
        {
          //Rate control
          for (i=0; i<16; i++)
            for(j=0; j<16; j++)
              diffy[j][i] = imgY_org[img->pix_y+j][img->pix_x+i]-img->mprr_2[i16mode][j][i];
           
            best_mode   = I16MB;
            currMB->cbp = dct_luma_16x16 (i16mode); //++ 对当前宏块采用intra16*16类型进行编码,并计算CBP
        }
      }
    }
   
    if (rerun==0)
    {
      intra1 = (currMB->mb_type==I16MB || currMB->mb_type==I4MB ? 1 : 0);
    }
} // for (rerun=0; rerun<runs; rerun++)

if (input->rdopt)
{
   
    if ((cbp!=0 || best_mode==I16MB ))
      currMB->prev_cbp = 1;
    else if (cbp==0 && !input->RCEnable)
    {
      currMB->delta_qp = 0;
      currMB->qp = currMB->prev_qp;
      img->qp = currMB->qp;
      currMB->prev_cbp = 0;
    }

    set_stored_macroblock_parameters ();
}
else
{
    //===== set parameters for chosen mode =====
    SetModesAndRefframeForBlocks (best_mode); //++ 设置当前宏块的参数,包括:宏块类型(mb_type)、4个8*8块的分割模式和预测方向(b8mode,b8pdir)、16个4*4块的参考帧索引(ref_idx,ref_pic_id)
    if (best_mode==P8x8)
    {
      SetCoeffAndReconstruction8x8 (currMB);
    }
    else
    {
      if (best_mode!=I4MB)
      {
        for (k=0, j=img->block_y; j<img->block_y+4; j++)
          for (     i=img->block_x; i<img->block_x+4; i++, k++)
          {
            ipredmodes    [i][j] = DC_PRED;
            currMB->intra_pred_modes[k] = DC_PRED;
          }
          if (best_mode!=I16MB)
          {
            LumaResidualCoding ();
            //Rate control
            for (i=0; i<16; i++)
              for(j=0; j<16; j++)
                diffy[j][i] = imgY_org[img->pix_y+j][img->pix_x+i]-img->mpr[i][j];
          }
      }
    }
    // precompute all chroma intra prediction modes
    IntraChromaPrediction8x8(NULL, NULL, NULL); //++ 对色度块进行处理,包括:分别计算4种色度帧内预测模式下的预测块、代价(该分支未采用RDO,因此以SATD作为判断标准)、最佳预测模式
    img->i16offset = 0;
    dummy = 0;
    ChromaResidualCoding (&dummy);
    if (best_mode==I16MB)
    {
      img->i16offset = I16Offset (currMB->cbp, i16mode);
    }
    SetMotionVectorsMB (currMB, bframe);
   
    //===== check for SKIP mode =====
    if ((img->type==P_SLICE || img->type==SP_SLICE) && best_mode==1 && currMB->cbp==0 &&
      enc_picture->ref_idx[LIST_0][img->block_x][img->block_y]==0 &&
      enc_picture->mv[LIST_0][img->block_x][img->block_y][0]==allmvs[0][0][0][0][0][0] &&
      enc_picture->mv[LIST_0][img->block_x][img->block_y][1]==allmvs[0][0][0][0][0][1]               )
    {
      currMB->mb_type=currMB->b8mode[0]=currMB->b8mode[1]=currMB->b8mode[2]=currMB->b8mode[3]=0;
    }
   
    if(img->MbaffFrameFlag)
      set_mbaff_parameters();
}

// Rate control
if(input->RCEnable)
{  
    if(img->type==P_SLICE)
    {
      img->MADofMB[img->current_mb_nr] = calc_MAD();
     
      if(input->basicunit<img->Frame_Total_Number_MB)
      {
        img->TotalMADBasicUnit +=img->MADofMB[img->current_mb_nr];
       
        /* delta_qp is present only for non-skipped macroblocks*/
        if ((cbp!=0 || best_mode==I16MB))
          currMB->prev_cbp = 1;
        else
        {
          img->qp -= currMB->delta_qp;
          currMB->delta_qp = 0;
          currMB->qp = img->qp;
          currMB->prev_cbp = 0;
        }
        /* When MBAFF is used, delta_qp is only present for the first non-skipped macroblock of each
        macroblock pair*/
        if (input->MbInterlace)
        {
          if(!currMB->mb_field)
          {
            DELTA_QP = currMB->delta_qp;
            QP      = currMB->qp;
          }
          else
          {
            DELTA_QP2 = currMB->delta_qp;
            QP2      = currMB->qp;
          }
        }      
      }
    }
}

   
if(input->rdopt)
    rdopt->min_rdcost = min_rdcost;
else
    rdopt->min_rdcost = min_cost;

if(img->MbaffFrameFlag)
{
    if (img->current_mb_nr%2) //bottom
    {
      if ((currMB->mb_type ? 0:((img->type == B_SLICE) ? !currMB->cbp:1)) // bottom is skip
        &&(prevMB->mb_type ? 0:((img->type == B_SLICE) ? !prevMB->cbp:1))) // top is skip
      {
        if (!(field_flag_inference() == curr_mb_field))
        {
          rdopt->min_rdcost = 1e30; // don't allow coding of an MB pair as skip if wrong inference
        }
      }
    }
}

//===== Decide if this MB will restrict the reference frames =====
if (input->RestrictRef==1)
{
    if (input->rdopt==1)
    {
      refresh_map[2*img->mb_y ][2*img->mb_x ] = (intra ? 1 : 0);
      refresh_map[2*img->mb_y ][2*img->mb_x+1] = (intra ? 1 : 0);
      refresh_map[2*img->mb_y+1][2*img->mb_x ] = (intra ? 1 : 0);
      refresh_map[2*img->mb_y+1][2*img->mb_x+1] = (intra ? 1 : 0);
    }
    else if (input->rdopt==2)
    {
      refresh_map[2*img->mb_y ][2*img->mb_x ] = (intra1==0 && (currMB->mb_type==I16MB || currMB->mb_type==I4MB) ? 1 : 0);
      refresh_map[2*img->mb_y ][2*img->mb_x+1] = (intra1==0 && (currMB->mb_type==I16MB || currMB->mb_type==I4MB) ? 1 : 0);
      refresh_map[2*img->mb_y+1][2*img->mb_x ] = (intra1==0 && (currMB->mb_type==I16MB || currMB->mb_type==I4MB) ? 1 : 0);
      refresh_map[2*img->mb_y+1][2*img->mb_x+1] = (intra1==0 && (currMB->mb_type==I16MB || currMB->mb_type==I4MB) ? 1 : 0);
    }
}
else if (input->RestrictRef==2)
{
    refresh_map[2*img->mb_y ][2*img->mb_x ] = (currMB->mb_type==I16MB || currMB->mb_type==I4MB ? 1 : 0);
    refresh_map[2*img->mb_y ][2*img->mb_x+1] = (currMB->mb_type==I16MB || currMB->mb_type==I4MB ? 1 : 0);
    refresh_map[2*img->mb_y+1][2*img->mb_x ] = (currMB->mb_type==I16MB || currMB->mb_type==I4MB ? 1 : 0);
    refresh_map[2*img->mb_y+1][2*img->mb_x+1] = (currMB->mb_type==I16MB || currMB->mb_type==I4MB ? 1 : 0);
}

if(input->FMEnable)
    skip_intrabk_SAD(best_mode, listXsize[LIST_0+list_offset]);
}

原创粉丝点击