mode_decision.c

来自「the newest JM software by h.264 JVT offi」· C语言 代码 · 共 1,390 行 · 第 1/4 页

C
1,390
字号
          if (params->RCEnable)
          {
            if(mode == P8x8)
              rc_store_diff(img->opix_x, img->opix_y, currMB->luma_transform_size_8x8_flag == 1 ? tr8x8.mpr8x8 : tr4x4.mpr8x8);
            else
              rc_store_diff(img->opix_x, img->opix_y, pred);
          }

          store_macroblock_parameters (currMB, mode);

          if(params->rdopt == 2 && mode == 0 && params->EarlySkipEnable)
          {
            // check transform quantized coeff.
            if(currMB->cbp == 0)
              *inter_skip = 1;
          }
        }
        terminate_trans = transform_termination_control(currMB, mode, bslice);
      }while (!terminate_trans);
    }while (!terminate_16x16);

    // Encode with no coefficients. Currently only for direct. This could be extended to all other modes as in example.
    //if (mode < P8x8 && (*inter_skip == 0) && enc_mb->valid[mode] && currMB->cbp && (currMB->cbp&15) != 15 && !params->nobskip)
    if (bslice && mode == 0 && (*inter_skip == 0) && enc_mb->valid[mode] 
    && currMB->cbp && (currMB->cbp&15) != 15 && !params->nobskip
    && !(currMB->qp_scaled[0] == 0 && img->lossless_qpprime_flag==1) )
    {
      img->NoResidueDirect = 1;
      
      if (RDCost_for_macroblocks (currSlice, currMB, enc_mb->lambda_md, mode, min_rdcost, min_dcost, min_rate, i16mode, is_cavlc))
      {
        //Rate control
        if (params->RCEnable)
          rc_store_diff(img->opix_x,img->opix_y,pred);
        if (img->AdaptiveRounding)
          reset_adaptive_rounding_direct();
        store_macroblock_parameters (currMB, mode);
      }
    }
    
    //modes 0 and 1 of a B frame 
    if (img->AdaptiveRounding && bslice && mode <= 1)
    { 
      if (luma_transform_size_8x8_flag)
        update_adaptive_rounding_16x16( img, img->ARCofAdj8x8, mode);
      else
        update_adaptive_rounding_16x16( img, img->ARCofAdj4x4, mode);
    }
  }
}


/*!
*************************************************************************************
* \brief
*    Mode Decision for an 8x8 sub-macroblock
*************************************************************************************
*/
void submacroblock_mode_decision(Slice *currSlice, 
                                 RD_PARAMS *enc_mb,
                                 RD_8x8DATA *dataTr,
                                 Macroblock *currMB,
                                 int ****cofACtr,
                                 int *have_direct,
                                 short bslice,
                                 int block,
                                 int *cost_direct,
                                 int *cost,
                                 int *cost8x8_direct,
                                 int transform8x8,
                                 int is_cavlc)
{
  int64 curr_cbp_blk;
  double min_rdcost, rdcost = 0.0;
  int j0, i0, j1, i1;
  int i,j, k;
  int min_cost8x8, index;
  int mode;
  int bmcost[5] = {INT_MAX};
  int cnt_nonz = 0;
  int best_cnt_nonz = 0;
  int maxindex =  (transform8x8) ? 2 : 5;
  int block_x, block_y;
  int lambda_mf[3];
  
  int ****fadjust = transform8x8? img->ARCofAdj8x8 : img->ARCofAdj4x4;
  short bipred_me = 0;

  char best_pdir = 0;
  char best_ref[2] = {0, -1};
  imgpel  **mb_pred = img->mb_pred[0];
  Boolean valid_8x8 = FALSE;
  Boolean stored_state_8x8 = FALSE;

#ifdef BEST_NZ_COEFF
  int best_nz_coeff[2][2];
#endif

  //--- set coordinates ---
  j0 = ((block>>1)<<3);
  j1 = (j0>>2);
  i0 = ((block&0x01)<<3);
  i1 = (i0>>2);

#ifdef BEST_NZ_COEFF
  for(j = 0; j <= 1; j++)
  {
    for(i = 0; i <= 1; i++)
      best_nz_coeff[i][j] = img->nz_coeff[currMB->mb_nr][i1 + i][j1 + j] = 0;
  }
#endif

  if (transform8x8)
    currMB->luma_transform_size_8x8_flag = 1; //switch to transform size 8x8

  //--- store coding state before coding ---
  store_coding_state (currSlice, currMB, cs_cm);

  //=====  LOOP OVER POSSIBLE CODING MODES FOR 8x8 SUB-PARTITION  =====
  for (min_cost8x8 = INT_MAX, min_rdcost = 1e20, index = (bslice?0:1); index < maxindex; index++)
  {
    mode = b8_mode_table[index];
    *cost = 0;

    if (enc_mb->valid[mode] && (!(transform8x8 == 1 && mode > 4)) && (transform8x8 == 0 || mode != 0 || (mode == 0 && active_sps->direct_8x8_inference_flag)))
    {
      if (transform8x8)
      {
        currMB->valid_8x8 = TRUE;
      }

      valid_8x8 = TRUE;
      curr_cbp_blk = 0;

      if (mode==0)  //--- Direct8x8 Mode ---
      {        
        block_x = img->block_x + (block & 0x01)*2;
        block_y = img->block_y + (block & 0x02);
        best_ref[LIST_0] = direct_ref_idx[LIST_0][block_y][block_x];
        best_ref[LIST_1] = direct_ref_idx[LIST_1][block_y][block_x];
        best_pdir        = direct_pdir[block_y][block_x];
      } // if (mode==0)
      else
      {
        int64 ref_pic_num;
        char b_ref;

        //======= motion estimation for all reference frames ========
        //-----------------------------------------------------------
        memcpy(lambda_mf, enc_mb->lambda_mf, 3 * sizeof(int));
        if (params->CtxAdptLagrangeMult == 1)
        {
          lambda_mf[F_PEL] = (int)(lambda_mf[F_PEL] * lambda_mf_factor);
          lambda_mf[H_PEL] = (int)(lambda_mf[H_PEL] * lambda_mf_factor);
          lambda_mf[Q_PEL] = (int)(lambda_mf[Q_PEL] * lambda_mf_factor);
        }

        PartitionMotionSearch (currMB, mode, block, lambda_mf);

        //--- get cost and reference frame for LIST 0 prediction ---
        bmcost[LIST_0] = INT_MAX;
        list_prediction_cost(currMB, LIST_0, block, mode, enc_mb, bmcost, best_ref);

        //store LIST 0 reference index for every block
        block_x = img->block_x + (block & 0x01)*2;
        block_y = img->block_y + (block & 0x02);
        b_ref = best_ref[LIST_0];
        ref_pic_num = enc_picture->ref_pic_num[enc_mb->list_offset[LIST_0]][(short) b_ref];

        for (j = block_y; j< block_y + 2; j++)
        {
          memset(&enc_picture->motion.ref_idx [LIST_0][j][block_x], b_ref, 2 * sizeof(char));
        }

        for (j = block_y; j< block_y + 2; j++)
        {
          for (i = block_x; i < block_x + 2; i++)
          {
            enc_picture->motion.ref_pic_id[LIST_0][j][i] = ref_pic_num;
          }
        }

        for (j = 0; j< 2; j++)
        {
          memcpy(enc_picture->motion.mv[LIST_0][block_y + j][block_x], img->all_mv[LIST_0][(short) b_ref][mode][j1 + j][i1], 4 * sizeof(short));
        }


        if (bslice)
        {
          //--- get cost and reference frame for LIST 1 prediction ---
          bmcost[LIST_1] = INT_MAX;
          bmcost[BI_PRED] = INT_MAX;
          list_prediction_cost(currMB, LIST_1, block, mode, enc_mb, bmcost, best_ref);

          // Compute bipredictive cost between best list 0 and best list 1 references
          list_prediction_cost(currMB, BI_PRED, block, mode, enc_mb, bmcost, best_ref);

          // currently Bi prediction ME is only supported for modes 1, 2, 3 and only for ref 0 and only for ref 0
          if (is_bipred_enabled(mode))
          {
            list_prediction_cost(currMB, BI_PRED_L0, block, mode, enc_mb, bmcost, 0);
            list_prediction_cost(currMB, BI_PRED_L1, block, mode, enc_mb, bmcost, 0);
          }
          else
          {
            bmcost[BI_PRED_L0] = INT_MAX;
            bmcost[BI_PRED_L1] = INT_MAX;
          }

          //--- get prediction direction ----
          determine_prediction_list(mode, bmcost, best_ref, &best_pdir, cost, &bipred_me);

          //store backward reference index for every block
          for (k = LIST_0; k <= LIST_1; k++)
          {
            for (j = block_y; j< block_y + 2; j++)
            {
              memset(&enc_picture->motion.ref_idx[k][j][block_x], best_ref[k], 2 * sizeof(char));
            }
            if (bipred_me)
            {              
              for (j = 0; j< 2; j++)
              {
                memcpy(enc_picture->motion.mv[k][block_y + j][block_x], img->bipred_mv[bipred_me - 1][k][(short) best_ref[k]][mode][j1 + j][i1], 4 * sizeof(short));
              }
            }
            else
            {
              for (j = 0; j< 2; j++)
              {
                memcpy(enc_picture->motion.mv[k][block_y + j][block_x], img->all_mv[k][(short) best_ref[k]][mode][j1 + j][i1], 4 * sizeof(short));
              }
            }
          }
        } // if (bslice)
        else
        {
          best_pdir = 0;
          *cost     = bmcost[LIST_0];
        }
      } // if (mode!=0)

      //--- get and check rate-distortion cost ---
      rdcost = RDCost_for_8x8blocks (currSlice, currMB, &cnt_nonz, &curr_cbp_blk, enc_mb->lambda_md,
        block, mode, best_pdir, best_ref[LIST_0], best_ref[LIST_1], bipred_me, is_cavlc);

      //--- set variables if best mode has changed ---
      if (rdcost < min_rdcost)
      {
        min_cost8x8                  = *cost;
        min_rdcost                   = rdcost;
        dataTr->part8x8mode  [block] = mode;
        dataTr->part8x8pdir  [block] = best_pdir;
        dataTr->part8x8l0ref [block] = best_ref[LIST_0];
        dataTr->part8x8l1ref [block] = best_ref[LIST_1];
        dataTr->part8x8bipred[block] = bipred_me;

        currMB->b8mode[block] = mode;

#ifdef BEST_NZ_COEFF
        if (cnt_nonz)
        {
          for(i = 0; i <= 1; i++)
          {
            best_nz_coeff[i][0]= img->nz_coeff[currMB->mb_nr][i1 + i][j1    ];
            best_nz_coeff[i][1]= img->nz_coeff[currMB->mb_nr][i1 + i][j1 + 1];
          }
        }
        else
        {
          for(i = 0; i <= 1; i++)
          {
            best_nz_coeff[i][0]= 0;
            best_nz_coeff[i][1]= 0;
          }
        }
#endif

        //--- store number of nonzero coefficients ---
        best_cnt_nonz  = cnt_nonz;

        //--- store block cbp ---
        cbp_blk8x8 &= (~(0x33 << (((block>>1)<<3)+((block & 0x01)<<1)))); // delete bits for block
        cbp_blk8x8 |= curr_cbp_blk;

        //--- store coefficients ---
        memcpy(&cofACtr[0][0][0][0],&img->cofAC[block][0][0][0], 4 * 2 * 65 * sizeof(int));

        if( img->P444_joined ) 
        {
          //--- store coefficients ---
          memcpy(&cofACtr[1][0][0][0],&img->cofAC[block + 4][0][0][0], 4 * 2 * 65 * sizeof(int));
          memcpy(&cofACtr[2][0][0][0],&img->cofAC[block + 8][0][0][0], 4 * 2 * 65 * sizeof(int));
        }

        //--- store reconstruction and prediction ---
        for (j = j0; j < j0 + BLOCK_SIZE_8x8; j++)
        {
          memcpy(&dataTr->rec_mbY8x8[j][i0],&enc_picture->imgY[img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
          memcpy(&dataTr->mpr8x8[j][i0],&mb_pred[j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
        }

        if (params->rdopt == 3)
        {
          errdo_store_best_block(decs->dec_mbY_best8x8[transform8x8], enc_picture->p_dec_img[0], i0, j0, img->pix_x + i0, img->pix_y, BLOCK_SIZE_8x8);
          errdo_store_best_block(decs->dec_mb_pred_best8x8[transform8x8], decs->dec_mb_pred, i0, j0, i0, 0, BLOCK_SIZE_8x8); 
        }

        if(img->type==SP_SLICE && (!si_frame_indicator))
        {
          for (j = j0; j < j0 + BLOCK_SIZE_8x8; j++)
          {
            memcpy(&dataTr->lrec[j][i0],&lrec[img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(int));
          }
        }

        if(img->P444_joined) 
        {
          for (j=j0; j<j0+8; j++)    
          {
            memcpy(&dataTr->rec_mb8x8_cr[0][j][i0],&enc_picture->imgUV[0][img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
            memcpy(&dataTr->rec_mb8x8_cr[1][j][i0],&enc_picture->imgUV[1][img->pix_y + j][img->pix_x + i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
            memcpy(&dataTr->mpr8x8CbCr[0][j][i0],&img->mb_pred[1][j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
            memcpy(&dataTr->mpr8x8CbCr[1][j][i0],&img->mb_pred[2][j][i0], BLOCK_SIZE_8x8 * sizeof(imgpel));
          }
        }


        //--- store best 8x8 coding state ---
        if (block < 3)
        {
          store_coding_state (currSlice, currMB, cs_b8);
          stored_state_8x8 = TRUE;
        }
      } // if (rdcost <= min_rdcost)

      //--- re-set coding state as it was before coding with current mode was performed ---
      reset_coding_state (currSlice, currMB, cs_cm);
    } // if ((enc_mb->valid[mode] && (transform8x8 == 0 || mode != 0 || (mode == 0 && active_sps->direct_8x8_inference_flag)))
  } // for (min_rdcost=1e30, index=(bslice?0:1); index<6; index++)

  if (valid_8x8 == TRUE)
  {
#ifdef BEST_NZ_COEFF
    for(i = 0; i <= 1; i++)  
    {
      for(j = 0; j <= 1; j++)

⌨️ 快捷键说明

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