By jack_incredible
//位于macroblock.c中
void IntraChromaPrediction8x8 (int *mb_up, int *mb_left, int*mb_up_left)
{
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
int s, s0, s1, s2, s3, i, j, k;
pel_t** image;
int block_x, block_y;
int mb_nr = img->current_mb_nr;
int mb_available_up;
int mb_available_left[2];
int mb_available_up_left;
int ih,iv;
int ib,ic,iaa;
int uv;
int hline[8], vline[9];
int mode;
int best_mode = DC_PRED_8; //just an initilaization here, should always be overwritten
int cost;
int min_cost;
int diff[16];
PixelPos up; //!< pixel position p(0,-1)
PixelPos left[9]; //!< pixel positions p(-1, -1..8)
for (i=0;i<9;i++)
{
getNeighbour(mb_nr, -1 , i-1 , 0, &left[i]); //判断左上边像素加上左边8个像素(共9个像素)的有效性,若有效取得其位置信息。
}
getNeighbour(mb_nr, 0 , -1 , 0, &up); //判断上边左起第一个像素的有效性
mb_available_up = up.available;
mb_available_up_left = left[0].available;
mb_available_left[0] = mb_available_left[1] = left[1].available;
if(input->UseConstrainedIntraPred) // input->UseConstrainedIntraPred参数来自配置文件,一般情况下为0,即不执行下面块中的程序
{
mb_available_up = up.available ? img->intra_block[up.mb_addr] : 0;
for (i=1, mb_available_left[0]=1; i<5;i++)
mb_available_left[0] &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;
for (i=5, mb_available_left[1]=1; i<9;i++)
mb_available_left[1] &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;
mb_available_up_left = left[0].available ? img->intra_block[left[0].mb_addr]: 0;
}
if (mb_up)
*mb_up = mb_available_up;
if (mb_left)
*mb_left = mb_available_left[0] && mb_available_left[1];
if( mb_up_left )
*mb_up_left = mb_available_up_left;
// compute all chroma intra prediction modes for both U and V
for (uv=0; uv<2; uv++)
{
image = enc_picture->imgUV[uv];
// DC prediction
for (block_y=0; block_y<8; block_y+=4)
for (block_x=0; block_x<8; block_x+=4)
{
s=128;
s0=s1=s2=s3=0;
//===== get prediction value =====
switch ((block_y>>1) + (block_x>>2))
{
case 0: //===== TOP LEFT ===== //8x8块的左上边4x4部分进行预测
if (mb_available_up) for (i=0;i<4;i++) s0 += image[up.pos_y][up.pos_x + i];
if (mb_available_left[0]) for (i=1;i<5;i++) s2 += image[left[i].pos_y][left[i].pos_x];
if (mb_available_up && mb_available_left[0]) s = (s0+s2+4) >> 3;
else if (mb_available_up) s = (s0 +2) >> 2;
else if (mb_available_left[0]) s = (s2 +2) >> 2;
break;
case 1: //===== TOP RIGHT ===== //8x8块的右上边4x4部分进行预测
if (mb_available_up) for (i=4;i<8;i++) s1 += image[up.pos_y][up.pos_x + i];
else if (mb_available_left[0]) for (i=1;i<5;i++) s2 += image[left[i].pos_y][left[i].pos_x];
if (mb_available_up) s = (s1 +2) >> 2;
else if (mb_available_left[0]) s = (s2 +2) >> 2;
break;
case 2: //===== BOTTOM LEFT ===== //8x8块的左下边4x4部分进行预测
if (mb_available_left[1]) for (i=5;i<9;i++) s3 += image[left[i].pos_y][left[i].pos_x];
else if (mb_available_up) for (i=0;i<4;i++) s0 += image[up.pos_y][up.pos_x + i];
if (mb_available_left[1]) s = (s3 +2) >> 2;
else if (mb_available_up) s = (s0 +2) >> 2;
break;
case 3: //===== BOTTOM RIGHT ===== //8x8块的右下边4x4部分进行预测
if (mb_available_up) for (i=4;i<8;i++) s1 += image[up.pos_y][up.pos_x + i];
if (mb_available_left[1]) for (i=5;i<9;i++) s3 += image[left[i].pos_y][left[i].pos_x];
if (mb_available_up && mb_available_left[1]) s = (s1+s3+4) >> 3;
else if (mb_available_up) s = (s1 +2) >> 2;
else if (mb_available_left[1]) s = (s3 +2) >> 2;
break;
}
//===== prediction =====
for (j=block_y; j<block_y+4; j++)
for (i=block_x; i<block_x+4; i++)
{
img->mprr_c[uv][DC_PRED_8][i][j] = s;
}
}
// vertical prediction
if (mb_available_up)
{
for (i=0; i<8; i++)
hline[i] = image[up.pos_y][up.pos_x + i];
for (i=0; i<8; i++)
for (j=0; j<8; j++)
img->mprr_c[uv][VERT_PRED_8][i][j] = hline[i];
}
// horizontal prediction
if (mb_available_left[0] && mb_available_left[1])
{
for (i=1; i<9; i++)
vline[i] = image[left[i].pos_y][left[i].pos_x];
for (i=0; i<8; i++)
for (j=0; j<8; j++)
img->mprr_c[uv][HOR_PRED_8][i][j] = vline[j+1];
}
// plane prediction
if (mb_available_left[0] && mb_available_left[1] && mb_available_up && mb_available_up_left)
{
ih = 4*(hline[7] - image[left[0].pos_y][left[0].pos_x]);
iv = 4*(vline[7+1] - image[left[0].pos_y][left[0].pos_x]);
for (i=1;i<4;i++)
{
ih += i*(hline[3+i] - hline[3-i]);
iv += i*(vline[3+i+1] - vline[3-i+1]);
}
ib=(17*ih+16)>>5;
ic=(17*iv+16)>>5;
iaa=16*(hline[7]+vline[7+1]);
for (j=0; j<8; j++)
for (i=0; i<8; i++)
img->mprr_c[uv][PLANE_8][i][j]=max(0,min(255,(iaa+(i-3)*ib +(j-3)*ic + 16)/32));// store plane prediction
}
} //end…for (uv=0; uv<2; uv++)
//这个地方貌似好像有点问题,觉得input->rdopt前不应该取!
if (!input->rdopt) // the rd-opt part does not work correctly (see encode_one_macroblock)
{ // since ipredmodes could be overwritten => encoder-decoder-mismatches
// pick lowest cost prediction mode
min_cost = 1<<20;
for (i=0;i<8;i++)
{
getNeighbour(mb_nr, 0 , i , 0, &left[i]); //获得当前块左边第一列的坐标
}
for (mode=DC_PRED_8; mode<=PLANE_8; mode++)
{
if ((mode==VERT_PRED_8 && !mb_available_up) ||
(mode==HOR_PRED_8 && (!mb_available_left[0] || !mb_available_left[1])) ||
(mode==PLANE_8 && (!mb_available_left[0] || !mb_available_left[1] || !mb_available_up || !mb_available_up_left)))
continue;
cost = 0;
for (uv=0; uv<2; uv++)
{
image = imgUV_org[uv];
for (block_y=0; block_y<8; block_y+=4)
for (block_x=0; block_x<8; block_x+=4)
{
for (k=0,j=block_y; j<block_y+4; j++)
for (i=block_x; i<block_x+4; i++,k++)
{
diff[k] = image[left[j].pos_y][left[j].pos_x+i] - img->mprr_c[uv][mode][i][j]; //求差分值
}
cost += SATD(diff, input->hadamard); //SATD变换
}
}
if (cost < min_cost)
{
best_mode = mode;
min_cost = cost;
}
}
currMB->c_ipred_mode = best_mode;
}
}