📄 adaptive_filter_decision.c
字号:
}
return 0;
}
//
// Decide filter usage by exhaustive search
//
static void Exhaustive(double C[2][2][D_SIZE][D_SIZE], int AvailFilter[D_SIZE], int nBits[D_SIZE], int D[D_SIZE])
{
int i, j;
int decision;
double BestCost = DBL_MAX;
double TmpCost;
int TmpD[D_SIZE] = {0};
double lambda;
#ifdef RDO_Q
int qp = input->UseRDO_Q ? img->masterQP:img->qp;
#else
int qp = img->qp;
#endif
if ((img->type==B_SLICE) && img->nal_reference_idc)
{
lambda = img->lambda_me[5][qp];
}
else
{
lambda = img->lambda_me[img->type][qp];
}
for(decision = 0; decision < (1 << D_SIZE); ++decision)
{
if(is_incompatible(decision, AvailFilter, TmpD))
continue;
TmpCost = 0.0;
for(i = 0; i < D_SIZE; ++i)
for(j = 0; j < D_SIZE; ++j)
TmpCost += C[TmpD[i]][TmpD[j]][i][j];
for(i = 0; i < D_SIZE; ++i)
if(TmpD[i])
TmpCost += BitCost(i, nBits, TmpD) * lambda;
if(TmpCost < BestCost)
{
BestCost = TmpCost;
for(i = 0; i < D_SIZE; ++i)
D[i] = TmpD[i];
}
}
}
//
// SAD-based optimal decision on the integer and sub-pel positions
//
void AIFDecision(int *FilterFlagInt, int *FilterFlag, int *SymmetryPosition)
{
int img_width, img_height;
int mbx, mby;
int x_orig, y_orig;
int curr_mb_nr;
int subblock;
int max_mb_nr = (img->width * img->height) / 256;
double C[2][2][D_SIZE][D_SIZE] = {{{{0.0}}}};
int nBits[D_SIZE] = {0}; // Bits required to encode offset and filter coefficients
int AvailFilter[D_SIZE] = {0}; // 1 if the corresponding filter is available
int D[D_SIZE] = {0}; // Decision vector (0/1 don't use/use corresponding filter)
int x, y;
int ref_frameF, ref_frameB;
int F_nrefs = 0; // Counts number of F and B references
int B_nrefs = 0;
int mvxF = 0;
int mvyF = 0;
int mvxB = 0;
int mvyB = 0;
int sub_posF = 0;
int sub_posB = 0;
imgpel **refYF = NULL;
imgpel **refYB = NULL;
int sub_pos;
float b_scaling = 1.0;
double pix_00, pix_01, pix_10, pix_11;
imgpel rec_00, rec_01, rec_10, rec_11;
imgpel orig;
int filterF, filterB;
int i, j;
double pixAifF, pixAifB;
double pixStdF, pixStdB;
#ifdef INTERNAL_BIT_DEPTH_INCREASE
imgpel max_pixel_value = (1 << img->bitdepth_luma) - 1;
#else
imgpel max_pixel_value = 255;
#endif
img_width = dpb.fs_ref[0]->frame->size_x;
img_height = dpb.fs_ref[0]->frame->size_y;
// Cost of encoding offset and coefficients
if(*FilterFlagInt && input->UseAdaptiveFilter == FILTER_TYPE_EDAIF)
{
nBits[SpPos2Idx(int_pos, D_SIZE)] = sendAIFInteger_EDAIF(NULL) + sendAIFOffset(-1, NULL);
AvailFilter[SpPos2Idx(int_pos, D_SIZE)] = 1;
}
for(sub_pos = a_pos; sub_pos <= o_pos; ++sub_pos)
{
if(SymmetryPosition[sub_pos] && FilterFlag[sub_pos])
{
nBits[SpPos2Idx(sub_pos, D_SIZE)] = estimateCostOfCoefs_EDAIF(sub_pos);
if(input->UseAdaptiveFilter == FILTER_TYPE_EDAIF)
nBits[SpPos2Idx(sub_pos, D_SIZE)] += sendAIFOffset(sub_pos, NULL);
AvailFilter[SpPos2Idx(sub_pos, D_SIZE)] |= FilterFlag[sub_pos];
}
}
// SAD computation
for(curr_mb_nr = 0; curr_mb_nr < max_mb_nr; ++curr_mb_nr)
{
mbx = curr_mb_nr % (img_width / MB_BLOCK_SIZE);
mby = curr_mb_nr / (img_width / MB_BLOCK_SIZE);
x_orig = mbx * MB_BLOCK_SIZE;
y_orig = mby * MB_BLOCK_SIZE;
if(IS_INTRA(&img->mb_data[curr_mb_nr]))
continue;
for(subblock = 0; subblock < 16; ++subblock)
{
x = x_orig + 4 * (subblock % 4);
y = y_orig + 4 * (subblock / 4);
ref_frameF = enc_picture->ref_idx[LIST_0][y / 4][x / 4];
ref_frameB = enc_picture->ref_idx[LIST_1][y / 4][x / 4];
if(IS_REF_VALID(ref_frameF))
{
mvxF = enc_picture->mv[LIST_0][y / 4][x / 4][0];
mvyF = enc_picture->mv[LIST_0][y / 4][x / 4][1];
sub_posF = GetSubPos(mvxF, mvyF);
refYF = listX[LIST_0][ref_frameF]->imgY;
++F_nrefs;
}
if(IS_REF_VALID(ref_frameB))
{
mvxB = enc_picture->mv[LIST_1][y / 4][x / 4][0];
mvyB = enc_picture->mv[LIST_1][y / 4][x / 4][1];
sub_posB = GetSubPos(mvxB, mvyB);
refYB = listX[LIST_1][ref_frameB]->imgY;
++B_nrefs;
}
// b_scaling computation
if(IS_REF_VALID(ref_frameF) && IS_REF_VALID(ref_frameB))
{
#ifdef USE_POC_WEIGHTS_IN_RDDECISION
int td, tb;
td = Clip3(-128, 127, (listX[LIST_1][ref_frameB]->poc - listX[LIST_0][ref_frameF]->poc));
tb = Clip3(-128, 127, (enc_picture->poc - listX[LIST_0][ref_frameF]->poc));
if (td != 0)
b_scaling = (float) tb / (float) td; // POC-based
else
#endif
b_scaling = 0.5; // 1/2
}
else if(IS_REF_VALID(ref_frameF) || IS_REF_VALID(ref_frameB))
{
b_scaling = 1.0;
}
// Check if the filters exist and is primary
filterF = IS_REF_VALID(ref_frameF)? ((sub_posF == int_pos)? *FilterFlagInt: FilterFlag[sub_posF]): 0;
filterB = IS_REF_VALID(ref_frameB)? ((sub_posB == int_pos)? *FilterFlagInt: FilterFlag[sub_posB]): 0;
if(!filterF && !filterB)
continue;
// Bidirectional
if(IS_REF_VALID(ref_frameF) && IS_REF_VALID(ref_frameB))
{
for(i = y; i < y + 4; ++i)
{
for(j = x; j < x + 4; ++j)
{
if(filterF)
pixAifF = GetAIFPixel(refYF, i, j, sub_posF, mvxF, mvyF, AIF_INTERPOLATION);
else
pixAifF = GetAIFPixel(refYF, i, j, sub_posF, mvxF, mvyF, STD_INTERPOLATION);
if(filterB)
pixAifB = GetAIFPixel(refYB, i, j, sub_posB, mvxB, mvyB, AIF_INTERPOLATION);
else
pixAifB = GetAIFPixel(refYB, i, j, sub_posB, mvxB, mvyB, STD_INTERPOLATION);
pixStdF = GetAIFPixel(refYF, i, j, sub_posF, mvxF, mvyF, STD_INTERPOLATION);
pixStdB = GetAIFPixel(refYB, i, j, sub_posB, mvxB, mvyB, STD_INTERPOLATION);
pix_00 = (1 - b_scaling) * pixStdF + b_scaling * pixStdB;
pix_01 = (1 - b_scaling) * pixStdF + b_scaling * pixAifB;
pix_10 = (1 - b_scaling) * pixAifF + b_scaling * pixStdB;
pix_11 = (1 - b_scaling) * pixAifF + b_scaling * pixAifB;
rec_00 = max(0, min(max_pixel_value, (int)(pix_00 + 0.5)));
rec_01 = max(0, min(max_pixel_value, (int)(pix_01 + 0.5)));
rec_10 = max(0, min(max_pixel_value, (int)(pix_10 + 0.5)));
rec_11 = max(0, min(max_pixel_value, (int)(pix_11 + 0.5)));
orig = (int)(imgY_org[i][j]);
if(filterF && filterB)
{
// Both filters are valid
C[0][0][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_00);
C[1][1][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_11);
if(sub_posF != sub_posB)
{
// Sub-pel positions are not using the same filter
C[0][1][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_01);
C[1][0][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_10);
}
}
else if(filterF)
{
// Filter F is valid
C[0][0][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_00);
C[1][0][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_10);
}
else
{
// Filter B is valid
C[0][0][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_00);
C[0][1][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posB, D_SIZE)] += (double)abs(orig - rec_01);
}
}
}
}
else
{
if(IS_REF_VALID(ref_frameB))
{
if(!filterB)
{
continue;
}
else
{
sub_posF = sub_posB;
mvxF = mvxB;
mvyF = mvyB;
refYF = refYB;
}
}
else if(!filterF)
{
continue;
}
for(i = y; i < y + 4; ++i)
{
for(j = x; j < x + 4; ++j)
{
pix_00 = GetAIFPixel(refYF, i, j, sub_posF, mvxF, mvyF, STD_INTERPOLATION);
pix_11 = GetAIFPixel(refYF, i, j, sub_posF, mvxF, mvyF, AIF_INTERPOLATION);
rec_00 = max(0, min(max_pixel_value, (int)(pix_00 + 0.5)));
rec_11 = max(0, min(max_pixel_value, (int)(pix_11 + 0.5)));
orig = (int)(imgY_org[i][j]);
C[0][0][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posF, D_SIZE)] += (double)abs(orig - rec_00);
C[1][1][SpPos2Idx(sub_posF, D_SIZE)][SpPos2Idx(sub_posF, D_SIZE)] += (double)abs(orig - rec_11);
}
}
} // Bidirectional if
} // Subblock loop
} // Macroblock loop
// Decision
if((F_nrefs == 0) || (B_nrefs == 0))
Diagonal(C, AvailFilter, nBits, D); // All references from the same direction
else
Exhaustive(C, AvailFilter, nBits, D);
// Output
*FilterFlagInt = D[0];
for(i = 1; i < D_SIZE; ++i)
FilterFlag[Idx2SpPos(i, D_SIZE)] = D[i];
}
#endif // E_DAIF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -