📄 switched_filters.c
字号:
// While SAD can be improved
while((minSAD = get_min_d(err, min_d, tmp_d, oldSAD)) < oldSAD)
{
oldSAD = minSAD;
memcpy(min_d, tmp_d, sizeof(int) * 16);
}
// Copy result
memcpy(out, min_d, sizeof(int) * 16);
}
//
// Compute filter combination for frame and sequence
//
static void ComputeFilterCombination_B()
{
ComputeFilterCombination_B_gd(AccErrorB, BestCombFilterB);
ComputeFilterCombination_B_gd(SequenceAccErrorB, SequenceBestCombFilterB);
}
//
//
//
static void ResetAll(int slice)
{
int a, b, c, d;
static int firstP = 1;
static int firstB = 1;
if(slice == P_SLICE)
{
memset(SamplesSubPelOffset, 0, 16 * sizeof(int));
memset(SamplesFrameOffsetP, 0, MAX_REFERENCE_PICTURES * sizeof(int));
for(a = 0; a < NUM_SIFO; ++a)
for(b = 0; b < 16; ++b)
AccErrorP[a][b] = 0;
for(a = 0; a < MAX_REFERENCE_PICTURES; ++a)
for(b = 0; b < 16; ++b)
for(c = 0; c < NUM_SIFO; ++c)
AccFrameOffsetP[a][b][c] = 0;
if(firstP == 1)
{
firstP = 0;
for(a = 0; a < 16; ++a)
for(b = 0; b < NUM_SIFO; ++b)
SequenceAccErrorP[b][a] = 0;
}
else
{
for(a = 0; a < 16; ++a)
for(b = 0; b < NUM_SIFO; ++b)
SequenceAccErrorP[b][a] *= NORM_FACTOR;
}
}
else if(slice == B_SLICE)
{
// Error
for(a = 0; a < NUM_SIFO; ++a)
for(b = 0; b < NUM_SIFO; ++b)
for(c = 0; c < 16; ++c)
for(d = 0; d < 16; ++d)
{
AccErrorB[a][b][c][d] = 0.0;
SamplesB[a][b][c][d] = 0;
}
// Frame offsets
for(a = 0; a < MAX_REFERENCE_PICTURES; ++a)
{
AccFrameOffsetF[a] = AccFrameOffsetB[a] = 0;
FrameOffsetF[a] = FrameOffsetB[a] = 0;
SamplesFrameOffsetF[a] = SamplesFrameOffsetB[a] = 0;
}
// SubPel offsets
memset(AccSubPelOffsetF, 0, 16 * sizeof(double));
memset(AccSubPelOffsetB, 0, 16 * sizeof(double));
memset(SubPelOffsetF, 0, 16 * sizeof(int));
memset(SubPelOffsetB, 0, 16 * sizeof(int));
memset(SamplesSubPelOffsetF, 0, 16 * sizeof(int));
memset(SamplesSubPelOffsetB, 0, 16 * sizeof(int));
memset(BestCombFilterB, 0, 16 * sizeof(int));
if(firstB == 1)
{
firstB = 0;
memset(SequenceBestCombFilterB, 0, 16 * sizeof(int));
for(a = 0; a < NUM_SIFO; ++a)
for(b = 0; b < NUM_SIFO; ++b)
for(c = 0; c < 16; ++c)
for(d = 0; d < 16; ++d)
SequenceAccErrorB[a][b][c][d] = 0;
}
else
{
for(a = 0; a < NUM_SIFO; ++a)
for(b = 0; b < NUM_SIFO; ++b)
for(c = 0; c < 16; ++c)
for(d = 0; d < 16; ++d)
SequenceAccErrorB[a][b][c][d] *= NORM_FACTOR;
}
}
}
//
// Return the value of a pixel interpolated with filter filterNo
//
static int GetInterpolatedPixel(unsigned short ** img, int icoord, int jcoord,
int img_width, int img_height, int sub_pos, int filterNo)
{
int pos_x, pos_y;
double ipVal;
int out;
int ii, jj;
int i, j;
#define FILTER_SIZE 6 // Undefined at the end of the function
#define FILTER_OFFSET (6 / 2 - 1) // Undefined at the end of the function
assert(filterNo < NUM_SIFO);
ipVal = 0.0;
i = icoord - 4 * IMG_PAD_SIZE;
j = jcoord - 4 * IMG_PAD_SIZE;
if(sub_pos)
{
for(ii = 0; ii < FILTER_SIZE; ++ii)
{
for(jj = 0; jj < FILTER_SIZE; ++jj)
{
pos_y = Clip3Fun(0, img_height - 1, i / 4 - FILTER_OFFSET + ii);
if((i < 0) && (pos_y > 0))
pos_y -= 1;
pos_x = Clip3Fun(0, img_width - 1, j / 4 - FILTER_OFFSET + jj);
if((j < 0) && (pos_x > 0))
pos_x -=1;
ipVal += (SIFO_FILTER[filterNo][sub_pos - 1][FILTER_SIZE * ii + jj] * img[pos_y][pos_x]);
}
}
out = Clip3Fun(0, 255, (int)(ipVal + 0.5));
}
else
{
out = img[Clip3Fun(0, img_height - 1, i / 4)][Clip3Fun(0, img_width - 1, j / 4)];
}
#undef FILTER_OFFSET
#undef FILTER_SIZE
return out;
}
//
//
//
static void AccumulateError_P(int x_orig, int y_orig)
{
int x, y, xj, yi, temp, valOrg;
int mvx = 0, mvy = 0;
int sub_pos = 0, mvx_sub, mvy_sub;
int ref_frame = 0;
int subblock = 0;
int out4Y_width = (img->width + 2 * IMG_PAD_SIZE) * 4 - 1;
int out4Y_height = (img->height + 2 * IMG_PAD_SIZE) * 4 - 1;
unsigned short ** imgY;
int f;
for(subblock = 0; subblock < 16; ++subblock)
{
x = x_orig + 4 * (subblock % 4);
y = y_orig + 4 * (subblock / 4);
mvx = enc_picture->mv[LIST_0][y / 4][x / 4][0];
mvy = enc_picture->mv[LIST_0][y / 4][x / 4][1];
mvx_sub = (mvx >= 0)? mvx % 4: (4 - abs(mvx) % 4) % 4;
mvy_sub = (mvy >= 0)? mvy % 4: (4 - abs(mvy) % 4) % 4;
sub_pos = mvx_sub + 4 * mvy_sub; // pos 0..15 in a 4x4 block
ref_frame = enc_picture->ref_idx[LIST_0][y / 4][x / 4];
if(ref_frame != -1)
{
imgY = listX[LIST_0][ref_frame]->imgY;
for(yi = 0; yi < 4; ++yi)
{
for(xj = 0; xj < 4; ++xj)
{
int xcoord = Clip3Fun(0, out4Y_width, 4 * (x + xj) + 4 * IMG_PAD_SIZE + mvx);
int ycoord = Clip3Fun(0, out4Y_height, 4 * (y + yi) + 4 * IMG_PAD_SIZE + mvy);
valOrg = imgY_org[y+yi][x+xj];
for(f = 0; f < NUM_SIFO; ++f)
{
temp = valOrg - GetInterpolatedPixel(imgY, ycoord, xcoord, img->width, img->height, sub_pos, f);
AccFrameOffsetP[ref_frame][sub_pos][f] += temp;
AccErrorP[f][sub_pos] += temp * temp;
}
SamplesFrameOffsetP[ref_frame]++;
if(ref_frame == 0)
SamplesSubPelOffset[sub_pos]++;
}
}
}
}
}
//
//
//
static void ComputeFiltersAndOffsets_P()
{
int i, frame, ind, offset;
double combAccSamplesFrameOffsetP[MAX_REFERENCE_PICTURES], combAccFrameOffsetP[16], minVal;
// Filter selection based on the current frame
for(i = 0; i < 16; ++i)
{
img->filterFrame[i] = 0;
minVal = AccErrorP[0][i];
for(ind = 1; ind < NUM_SIFO; ++ind)
{
if(AccErrorP[ind][i] < minVal)
{
img->filterFrame[i] = ind;
minVal = AccErrorP[ind][i];
}
}
}
// Frame offsets corresponding to the frame filters
for(frame = 0; frame < listXsize[LIST_0]; ++frame)
{
combAccFrameOffsetP[frame] = 0;
for(i = 0; i < 16; ++i)
combAccFrameOffsetP[frame] += AccFrameOffsetP[frame][i][img->filterFrame[i]];
img->imgOffset_list0[frame] = 0;
if(SamplesFrameOffsetP[frame] > 0)
{
offset = (int)(fabs(combAccFrameOffsetP[frame]) / (double)SamplesFrameOffsetP[frame] + 0.5);
img->imgOffset_list0[frame] = (combAccFrameOffsetP[frame] >= 0)? offset: -offset;
}
}
// Sub-pel offsets
for(i = 0; i < 16; ++i)
{
combAccSamplesFrameOffsetP[i] = AccFrameOffsetP[0][i][img->filterFrame[i]];
img->subpelOffset_list0[i] = 0;
if(SamplesSubPelOffset[i] > 0)
{
offset = (int)((double)fabs(combAccSamplesFrameOffsetP[i]) / (double)SamplesSubPelOffset[i] + 0.5);
img->subpelOffset_list0[i] = (combAccSamplesFrameOffsetP[i] >= 0)? offset: -offset;
}
}
}
//
//
//
static void UpdateSequenceFilters_P(void)
{
int i, f, ind;
double minVal;
// Filter selection based on the sequence
for(i = 0; i < 16; ++i)
{
for(f = 0; f < NUM_SIFO; ++f)
SequenceAccErrorP[f][i] += AccErrorP[f][i];
img->filterSequence[i] = 0;
minVal = SequenceAccErrorP[0][i];
for(ind = 1; ind < NUM_SIFO; ++ind)
{
if(SequenceAccErrorP[ind][i] < minVal)
{
img->filterSequence[i] = ind;
minVal = SequenceAccErrorP[ind][i];
}
}
}
}
//
// Accumulate squared error to compute best filter combination
//
static void AccumulateError_B(int x_orig, int y_orig)
{
int x, y, xj, yi, valOrg, i, j;
int mvx[2], mvy[2];
int sub_pos[2], mvx_sub, mvy_sub;
int ref_frame[2];
int subblock=0;
int out4Y_width = (img->width + 2 * IMG_PAD_SIZE) * 4 - 1;
int out4Y_height = (img->height + 2 * IMG_PAD_SIZE) * 4 - 1;
double tmp;
int apply_weights = ((img->filterParam == SIFO_SEQ_FILTER) && (active_pps->pic_parameter_set_id == 2));
unsigned short ** imgY0;
unsigned short ** imgY1;
unsigned short ** imgY;
int f;
for(subblock = 0; subblock < 16; ++subblock)
{
x = x_orig + 4 * (subblock % 4);
y = y_orig + 4 * (subblock / 4);
//get motion information
for (i = 0; i < 2; ++i)
{
mvx[i] = enc_picture->mv[LIST_0+i][y/4][x/4][0];
mvy[i] = enc_picture->mv[LIST_0+i][y/4][x/4][1];
mvx_sub = (mvx[i] >= 0)? mvx[i] % 4: (4 - abs(mvx[i]) % 4) % 4;
mvy_sub = (mvy[i] >= 0)? mvy[i] % 4: (4 - abs(mvy[i]) % 4) % 4;
sub_pos[i] = mvx_sub + 4 * mvy_sub; // Pos 0..15 in a 4x4 block
ref_frame[i] = enc_picture->ref_idx[LIST_0+i][y/4][x/4];
}
if ((ref_frame[0] == -1) && (ref_frame[1] == -1))
continue; // Intra macroblocks are not used for calculation
if ((ref_frame[0] != -1) && (ref_frame[1] != -1)) // Bi-predicted
{
int tempF[NUM_SIFO], tempB[NUM_SIFO];
int fw_ref_idx = ref_frame[0];
int bw_ref_idx = ref_frame[1];
imgY0 = listX[LIST_0][fw_ref_idx]->imgY;
imgY1 = listX[LIST_1][bw_ref_idx]->imgY;
for(yi = 0; yi < 4; ++yi)
{
for(xj = 0; xj < 4; ++xj)
{
int xcoord0 = Clip3Fun(0 , out4Y_width, 4 * (x + xj) + 4 * IMG_PAD_SIZE + mvx[0]);
int ycoord0 = Clip3Fun(0 , out4Y_height, 4 * (y + yi) + 4 * IMG_PAD_SIZE + mvy[0]);
int xcoord1 = Clip3Fun(0 , out4Y_width, 4 * (x + xj) + 4 * IMG_PAD_SIZE + mvx[1]);
int ycoord1 = Clip3Fun(0 , out4Y_height, 4 * (y + yi) + 4 * IMG_PAD_SIZE + mvy[1]);
valOrg = imgY_org[y + yi][x + xj];
for(f = 0; f < NUM_SIFO; ++f)
{
tempF[f] = GetInterpolatedPixel(imgY0, ycoord0, xcoord0, img->width, img->height, sub_pos[0], f);
tempB[f] = GetInterpolatedPixel(imgY1, ycoord1, xcoord1, img->width, img->height, sub_pos[1], f);
}
for(i = 0; i < NUM_SIFO; ++i)
{
for(j = 0; j < NUM_SIFO; ++j)
{
if(apply_weights)
{
tmp = valOrg - clip1a(((wbp_weight[0][fw_ref_idx][bw_ref_idx][0] * tempF[i] +
wbp_weight[1][fw_ref_idx][bw_ref_idx][0] * tempB[j] +
(wp_offset[0][fw_ref_idx][0] + wp_offset[1][bw_ref_idx][0]) * 2 * wp_luma_round +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -