📄 rdopt.c
字号:
*************************************************************************************
* \brief
* Store macroblock parameters
*************************************************************************************
*/
void
store_macroblock_parameters (int mode)
{
int i, j, k, ****i4p, ***i3p;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
int bframe = (img->type==B_IMG);
int **frefar = (img->type==B_IMG ? fw_refFrArr : refFrArr);
int **brefar = bw_refFrArr;
//--- store best mode ---
best_mode = mode;
for (i=0; i<4; i++)
{
b8mode[i] = currMB->b8mode[i];
b8pdir[i] = currMB->b8pdir[i];
}
//--- reconstructed blocks ----
if (!bframe && mode==0)
{
for (j=0; j<16; j++)
for (i=0; i<16; i++)
{
rec_mbY[j][i] = FastPelY_14 (mref[0], (img->pix_y+j)<<2, (img->pix_x+i)<<2);
}
for (j=0; j<8; j++)
for (i=0; i<8; i++)
{
rec_mbU[j][i] = mcef[0][0][img->pix_c_y+j][img->pix_c_x+i];
rec_mbV[j][i] = mcef[0][1][img->pix_c_y+j][img->pix_c_x+i];
}
}
else
{
for (j=0; j<16; j++)
for (i=0; i<16; i++)
{
rec_mbY[j][i] = imgY[img->pix_y+j][img->pix_x+i];
}
for (j=0; j<8; j++)
for (i=0; i<8; i++)
{
rec_mbU[j][i] = imgUV[0][img->pix_c_y+j][img->pix_c_x+i];
rec_mbV[j][i] = imgUV[1][img->pix_c_y+j][img->pix_c_x+i];
}
}
//--- store results of decoders ---
if (input->rdopt==2 && !bframe)
{
for (k=0; k<input->NoOfDecoders; k++)
{
for (j=img->pix_y; j<img->pix_y+16; j++)
for (i=img->pix_x; i<img->pix_x+16; i++)
{
// Keep the decoded values of each MB for updating the ref frames
decs->decY_best[k][j][i] = decs->decY[k][j][i];
}
}
}
//--- coeff, cbp, kac ---
if (mode || bframe)
{
i4p=cofAC; cofAC=img->cofAC; img->cofAC=i4p;
i3p=cofDC; cofDC=img->cofDC; img->cofDC=i3p;
cbp = currMB->cbp;
cbp_blk = currMB->cbp_blk;
}
else
{
cbp = cbp_blk = 0;
}
//--- references ---
frefframe[0] = frefar[img->block_y ][img->block_x ];
frefframe[1] = frefar[img->block_y ][img->block_x+2];
frefframe[2] = frefar[img->block_y+2][img->block_x ];
frefframe[3] = frefar[img->block_y+2][img->block_x+2];
if (bframe)
{
brefframe[0] = brefar[img->block_y ][img->block_x ];
brefframe[1] = brefar[img->block_y ][img->block_x+2];
brefframe[2] = brefar[img->block_y+2][img->block_x ];
brefframe[3] = brefar[img->block_y+2][img->block_x+2];
}
}
/*!
*************************************************************************************
* \brief
* Set stored macroblock parameters
*************************************************************************************
*/
void
set_stored_macroblock_parameters ()
{
int i, j, k, ****i4p, ***i3p;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
int mode = best_mode;
int bframe = (img->type==B_IMG);
int **frefar = (img->type==B_IMG ? fw_refFrArr : refFrArr);
int **brefar = bw_refFrArr;
//===== reconstruction values =====
for (j=0; j<16; j++)
for (i=0; i<16; i++)
{
imgY[img->pix_y+j][img->pix_x+i] = rec_mbY[j][i];
}
for (j=0; j<8; j++)
for (i=0; i<8; i++)
{
imgUV[0][img->pix_c_y+j][img->pix_c_x+i] = rec_mbU[j][i];
imgUV[1][img->pix_c_y+j][img->pix_c_x+i] = rec_mbV[j][i];
}
//===== coefficients and cbp =====
i4p=cofAC; cofAC=img->cofAC; img->cofAC=i4p;
i3p=cofDC; cofDC=img->cofDC; img->cofDC=i3p;
currMB->cbp = cbp;
currMB->cbp_blk = cbp_blk;
//==== macroblock type ====
currMB->mb_type = mode;
for (i=0; i<4; i++)
{
currMB->b8mode[i] = b8mode[i];
currMB->b8pdir[i] = b8pdir[i];
}
if (input->rdopt==2 && !bframe)
{
//! save the MB Mode of every macroblock
decs->dec_mb_mode[img->mb_x][img->mb_y] = mode;
}
//==== reference frames =====
for (j=0; j<4; j++)
for (i=0; i<4; i++)
{
frefar[img->block_y+j][img->block_x+i] = frefframe[2*(j/2) + (i/2)];
}
if (bframe)
{
for (j=0; j<4; j++)
for (i=0; i<4; i++)
{
brefar[img->block_y+j][img->block_x+i] = brefframe[2*(j/2) + (i/2)];
}
}
//==== intra prediction modes ====
if (mode==P8x8)
{
for (k=0, j=img->block_y+1; j<img->block_y+5; j++)
for ( i=img->block_x+1; i<img->block_x+5; i++, k++)
{
img ->ipredmode [i][j] = b8_ipredmode [k];
currMB->intra_pred_modes[k] = b8_intra_pred_modes[k];
}
}
else if (mode!=I4MB)
{
for (k=0, j=img->block_y+1; j<img->block_y+5; j++)
for ( i=img->block_x+1; i<img->block_x+5; i++, k++)
{
img ->ipredmode [i][j] = 0;
currMB->intra_pred_modes[k] = 0;
}
}
//==== motion vectors =====
SetMotionVectorsMB (currMB, bframe);
}
/*!
*************************************************************************************
* \brief
* Set reference frames and motion vectors
*************************************************************************************
*/
void
SetRefAndMotionVectors (int block, int mode, int ref, int pdir)
{
int i, j;
int bframe = (img->type==B_IMG);
int pmode = (mode==1||mode==2||mode==3?mode:4);
int j0 = ((block/2)<<1);
int i0 = ((block%2)<<1);
int j1 = j0 + (input->blc_size[pmode][1]>>2);
int i1 = i0 + (input->blc_size[pmode][0]>>2);
int** frefArr = (bframe ? fw_refFrArr : refFrArr);
int** brefArr = bw_refFrArr;
int*** fmvArr = (bframe ? tmp_fwMV : tmp_mv);
int*** bmvArr = tmp_bwMV;
if ((pdir==0 || pdir==2) && (mode!=IBLOCK && mode!=0))
{
for (j=j0; j<j1; j++)
for (i=i0; i<i1; i++)
{
fmvArr[0][img->block_y+j][img->block_x+i+4] = img->all_mv[i][j][ref][mode][0];
fmvArr[1][img->block_y+j][img->block_x+i+4] = img->all_mv[i][j][ref][mode][1];
frefArr [img->block_y+j][img->block_x+i ] = ref;
}
}
else
{
for (j=j0; j<j0+2; j++)
for (i=i0; i<i0+2; i++)
{
fmvArr[0][img->block_y+j][img->block_x+i+4] = 0;
fmvArr[1][img->block_y+j][img->block_x+i+4] = 0;
frefArr [img->block_y+j][img->block_x+i ] = -1;
}
}
if ((pdir==1 || pdir==2) && (mode!=IBLOCK && mode!=0))
{
for (j=j0; j<j0+2; j++)
for (i=i0; i<i0+2; i++)
{
bmvArr[0][img->block_y+j][img->block_x+i+4] = img->all_bmv[i][j][0][mode][0];
bmvArr[1][img->block_y+j][img->block_x+i+4] = img->all_bmv[i][j][0][mode][1];
brefArr [img->block_y+j][img->block_x+i ] = 0;
}
}
else if (bframe)
{
for (j=j0; j<j0+2; j++)
for (i=i0; i<i0+2; i++)
{
bmvArr[0][img->block_y+j][img->block_x+i+4] = 0;
bmvArr[1][img->block_y+j][img->block_x+i+4] = 0;
brefArr [img->block_y+j][img->block_x+i ] = -1;
}
}
}
/*!
*************************************************************************************
* \brief
* Mode Decision for a macroblock
*************************************************************************************
*/
void
encode_one_macroblock ()
{
static const int b8_mode_table[6] = {0, 4, 5, 6, 7, IBLOCK}; // DO NOT CHANGE ORDER !!!
static const int mb_mode_table[7] = {0, 1, 2, 3, P8x8, I16MB, I4MB}; // DO NOT CHANGE ORDER !!!
int valid[MAXMODE];
int rerun, block, index, mode, i0, i1, j0, j1, pdir, ref, i, j, k, ctr16x16, dummy;
double qp, lambda_mode, lambda_motion, min_rdcost, rdcost, max_rdcost=1e30;
int lambda_motion_factor;
int fw_mcost, bw_mcost, bid_mcost, mcost, max_mcost=(1<<30);
int curr_cbp_blk, cnt_nonz, best_cnt_nonz, best_fw_ref, best_pdir;
int cost, min_cost, cost8x8, cost_direct=0, have_direct=0, i16mode;
int intra1[4];
int intra = ((img->type==INTER_IMG && img->mb_y==img->mb_y_upd && img->mb_y_upd!=img->mb_y_intra) || img->type==INTRA_IMG);
int spframe = (img->type==INTER_IMG && img->types==SP_IMG);
int bframe = (img->type==B_IMG);
int write_ref = (input->no_multpred>1 || input->add_ref_frame>0);
int runs = (input->RestrictRef==1 && input->rdopt==2 && img->type==INTER_IMG ? 2 : 1);
int max_ref = img->nb_references;
int checkref = (input->rdopt && input->RestrictRef && img->type==INTER_IMG);
Macroblock* currMB = &img->mb_data[img->current_mb_nr];
//===== SET VALID MODES =====
valid[I4MB] = 1;
valid[I16MB] = 1;
// HS: I'm not sure when the Intra Mode on 8x8 basis should be unvalid
// Is it o.k. to have intra and inter 8x8 block inside one macroblock for SP-frame (especially for chroma)?
// Is it o.k. for data partitioning? (where the syntax elements have to written to?)
valid[IBLOCK] = 1;
valid[0] = (!intra && !spframe);
valid[1] = (!intra && input->InterSearch16x16);
valid[2] = (!intra && input->InterSearch16x8);
valid[3] = (!intra && input->InterSearch8x16);
valid[4] = (!intra && input->InterSearch8x8);
valid[5] = (!intra && input->InterSearch8x4);
valid[6] = (!intra && input->InterSearch4x8);
valid[7] = (!intra && input->InterSearch4x4);
valid[P8x8] = (valid[4] || valid[5] || valid[6] || valid[7] || (bframe && valid[0] && valid[IBLOCK]));
//===== SET LAGRANGE PARAMETERS =====
if (input->rdopt)
{
qp = (double)img->qp;
lambda_mode = 0.85 * pow (2, qp/3.0) * (bframe||spframe?4:1); // ????? WHY FACTOR 4 FOR SP-FRAME ?????
lambda_motion = sqrt (lambda_mode);
}
else
{
lambda_mode = lambda_motion = QP2QUANT[max(0,img->qp)];
}
lambda_motion_factor = LAMBDA_FACTOR (lambda_motion);
for (rerun=0; rerun<runs; rerun++)
{
if (runs==2)
{
if (rerun==0) input->rdopt=1;
else input->rdopt=2;
}
if (!intra)
{
//----- set search range ---
#if(Range_Decision)
new_search_range_x=Determine_Range(input->search_range,0);
new_search_range_y=Determine_Range(input->search_range,1);
#else
new_search_range_x=input->search_range;
new_search_range_y=input->search_range;
#endif
//===== set direct motion vectors =====
if (bframe)
{
Get_Direct_Motion_Vectors ();
}
if (valid[P8x8])
{
cost8x8 = 0;
//===== store coding state of macroblock =====
store_coding_state (cs_mb);
//===== LOOP OVER 8x8 SUB-PARTITIONS (Motion Estimation & Mode Decision) =====
for (cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
{
//--- set coordinates ---
j0 = ((block/2)<<3); j1 = (j0>>2);
i0 = ((block%2)<<3); i1 = (i0>>2);
//===== LOOP OVER POSSIBLE CODING MODES FOR 8x8 SUB-PARTITION =====
for (min_cost=(1<<20), min_rdcost=1e30, index=(bframe?0:1); index<6; index++)
{
if (valid[mode=b8_mode_table[index]])
{
curr_cbp_blk = 0;
if (mode==IBLOCK)
{
//--- Intra4x4 mode decision for 8x8 block ---
cnt_nonz = Mode_Decision_for_8x8IntraBlocks (block, lambda_mode, &cost);
best_fw_ref = -1;
best_pdir = -1;
} // if (mode==IBLOCK)
else if (mode==0)
{
//--- Direct Mode ---
if (!input->rdopt)
{
cost_direct += (cost = Get_Direct_Cost8x8 (block, lambda_mode));
have_direct ++;
}
best_fw_ref = -1;
best_pdir = 2;
} // if (mode==0)
else
{
//--- motion estimation for all reference frames ---
PartitionMotionSearch (mode, block, lambda_motion);
//--- get cost and reference frame for forward prediction ---
for (fw_mcost=max_mcost, ref=0; ref<max_ref; ref++)
{
if (!checkref || ref==0 || CheckReliabilityOfRef (block, ref, mode))
{
mcost = (input->rdopt ? write_ref ? REF_COST (lambda_motion_factor, ref) : 0 : (int)(2*lambda_motion*min(ref,1)));
mcost += motion_cost[mode][ref+1][block];
if (mcost < fw_mcost)
{
fw_mcost = mcost;
best_fw_ref = ref;
}
}
}
if (bframe)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -