📄 macroblock.c
字号:
int mb_y, mb_x, block8x8;
int list_mode[2];
short list_ref_idx[2], p_dir;
int num_blks;
int cost8x8=0, cost4x4=0;
int *diff_ptr;
short bipred_me;
imgpel (*mb_pred)[16] = img->mb_pred[0];
if(block_check==-1)
{
block8x8 = 0;
num_blks = 4;
}
else
{
block8x8 = block_check;
num_blks = block_check + 1;
}
for (; block8x8<num_blks; block8x8++)
{
SetModesAndRefframe (currMB, block8x8, &p_dir, list_mode, list_ref_idx);
bipred_me = currMB->bipred_me[block8x8];
mb_y = (block8x8 >> 1) << 3;
mb_x = (block8x8 & 0x01) << 3;
//===== prediction of 8x8 block =====
LumaPrediction (currMB, mb_x, mb_y, 8, 8, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1], bipred_me);
//===== loop over 4x4 blocks =====
for (k=0, block_y=mb_y; block_y<mb_y+8; block_y+=4)
{
for (block_x=mb_x; block_x<mb_x+8; block_x+=4)
{
//===== get displaced frame difference ======
diff_ptr=&diff64[k];
for (j=block_y; j<block_y + 4; j++)
{
for (i = block_x; i < block_x + 4; i++, k++)
diff64[k] = pCurImg[img->opix_y+j][img->opix_x + i] - mb_pred[j][i];
}
cost4x4 += distortion4x4 (diff_ptr);
}
}
cost8x8 += distortion8x8 (diff64);
}
if(params->Transform8x8Mode==2) //always allow 8x8 transform
return 1;
else if(cost8x8 < cost4x4)
return 1;
else
{
*cost += (cost4x4 - cost8x8);
return 0;
}
}
/*!
************************************************************************
* \brief
* Chroma residual coding for an macroblock
************************************************************************
*/
void ChromaResidualCoding (Macroblock *currMB, int is_cavlc)
{
int chroma_cbp;
static int uv, block8, block_y, block_x, j, i;
static int list_mode[2];
static short p_dir, list_ref_idx[2];
int skipped = (currMB->mb_type == 0 && (img->type == P_SLICE || img->type == SP_SLICE));
int yuv = img->yuv_format - 1;
short bipred_me;
imgpel (*mb_pred)[16] = NULL;
for (chroma_cbp = 0, uv=0; uv<2; uv++)
{
mb_pred = img->mb_pred[ uv + 1];
//===== prediction of chrominance blocks ===d==
block8 = 0;
for (block_y=0; block_y < img->mb_cr_size_y; block_y+=4)
for (block_x=0; block_x < img->mb_cr_size_x; block_x+=4)
{
block8 = block8x8_idx[yuv][block_y>>2][block_x>>2];
bipred_me = currMB->bipred_me[block8];
SetModesAndRefframe (currMB, block8, &p_dir, list_mode, list_ref_idx);
ChromaPrediction4x4 (currMB, uv, block_x, block_y, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1], bipred_me);
//ChromaPrediction (currMB, uv, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
}
// ==== set chroma residue to zero for skip Mode in SP frames
if (img->NoResidueDirect)
{
for (j=0; j<img->mb_cr_size_y; j++)
memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
}
else if (skipped && img->type==SP_SLICE)
{
for (j=0; j<img->mb_cr_size_y; j++)
memset(img->mb_ores[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
for (j=0; j<img->mb_cr_size_y; j++)
memset(img->mb_rres[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
}
else if (skipped)
{
for (j=0; j<img->mb_cr_size_y; j++)
memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
}
else
{
for (j=0; j<img->mb_cr_size_y; j++)
for (i=0; i<img->mb_cr_size_x; i++)
{
img->mb_ores[uv + 1][j][i] = pImgOrg[uv + 1][img->opix_c_y+j][img->opix_c_x+i] - mb_pred[j][i];
}
}
//===== DCT, Quantization, inverse Quantization, IDCT, and Reconstruction =====
//===== Call function for skip mode in SP frames to properly process frame ====
if (skipped && img->type==SP_SLICE)
{
if(si_frame_indicator || sp2_frame_indicator)
chroma_cbp = dct_chroma_sp2(currMB, uv,chroma_cbp, is_cavlc);
else
chroma_cbp = dct_chroma_sp(currMB, uv,chroma_cbp, is_cavlc);
}
else
{
if (!img->NoResidueDirect && !skipped)
{
if (img->type!=SP_SLICE || (currMB->mb_type==I16MB ))
{
//even if the block is intra it should still be treated as SP
chroma_cbp = dct_cr_4x4[uv] (currMB, uv,chroma_cbp, is_cavlc);
}
else
{
if(si_frame_indicator||sp2_frame_indicator)
chroma_cbp=dct_chroma_sp2(currMB, uv,chroma_cbp, is_cavlc);// SI frames or switching SP frames
else
chroma_cbp=dct_chroma_sp(currMB, uv,chroma_cbp, is_cavlc);
}
}
}
}
//===== update currMB->cbp =====
currMB->cbp += ((chroma_cbp)<<4);
}
/*!
**************************************************************************************
* \brief
* RD Decision for Intra prediction mode of the chrominance layers of one macroblock
**************************************************************************************
*/
void IntraChromaRDDecision (Macroblock *currMB, RD_PARAMS enc_mb)
{
int i, j, k;
imgpel** image;
int block_x, block_y;
int mb_available_up;
int mb_available_left[2];
int mb_available_up_left;
int uv;
int mode;
int best_mode = DC_PRED_8; //just an initialization here, should always be overwritten
int cost;
int min_cost;
PixelPos up; //!< pixel position p(0,-1)
PixelPos left[17]; //!< pixel positions p(-1, -1..15)
int cr_MB_x = img->mb_cr_size_x;
int cr_MB_y = img->mb_cr_size_y;
static imgpel *img_org, *img_prd;
static imgpel (*curr_mpr_16x16)[16][16];
for (i=0;i<cr_MB_y+1;i++)
{
getNeighbour(currMB, -1 , i-1 , img->mb_size[IS_CHROMA], &left[i]);
}
getNeighbour(currMB, 0 , -1 , img->mb_size[IS_CHROMA], &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(params->UseConstrainedIntraPred)
{
mb_available_up = up.available ? img->intra_block[up.mb_addr] : 0;
for (i=1, mb_available_left[0] = 1; i < (cr_MB_y>>1) + 1; i++)
mb_available_left[0] &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;
for (i=(cr_MB_y>>1) + 1, mb_available_left[1]=1; i < cr_MB_y + 1;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;
}
// pick lowest cost prediction mode
min_cost = INT_MAX;
for (i=0;i<cr_MB_y;i++)
{
getNeighbour(currMB, 0, i, img->mb_size[IS_CHROMA], &left[i]);
}
if ( img->MbaffFrameFlag && img->field_mode )
{
for (i=0;i<cr_MB_y;i++)
{
left[i].pos_y = left[i].pos_y >> 1;
}
}
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 = 1; uv < 3; uv++)
{
image = pImgOrg[uv];
curr_mpr_16x16 = img->mpr_16x16[uv];
for (block_y=0; block_y<cr_MB_y; block_y+=4)
{
for (block_x=0; block_x<cr_MB_x; block_x+=4)
{
for (k=0,j=block_y; j<block_y+4; j++)
{
img_prd = curr_mpr_16x16[mode][j];
img_org = &image[left[j].pos_y][left[j].pos_x];
for (i = block_x; i < block_x + 4; i++)
diff[k++] = img_org[i] - img_prd[i];
}
cost += distortion4x4(diff);
}
if (cost > min_cost) break;
}
if (cost > min_cost) break;
}
cost += (int) (enc_mb.lambda_me[Q_PEL] * mvbits[ mode ]); // exp golomb coding cost for mode signaling
if (cost < min_cost)
{
best_mode = mode;
min_cost = cost;
}
}
currMB->c_ipred_mode = best_mode;
}
/*!
************************************************************************
* \brief
* Check if all reference frames for a macroblock are zero
************************************************************************
*/
int ZeroRef (Macroblock* currMB)
{
int i,j;
for (j=img->block_y; j<img->block_y + BLOCK_MULTIPLE; j++)
{
for (i=img->block_x; i<img->block_x + BLOCK_MULTIPLE; i++)
{
if (enc_picture->motion.ref_idx[LIST_0][j][i]!=0)
return 0;
}
}
return 1;
}
/*!
************************************************************************
* \brief
* Converts macroblock type to coding value
************************************************************************
*/
int MBType2Value (Macroblock* currMB)
{
static const int dir1offset[3] = { 1, 2, 3};
static const int dir2offset[3][3] = {{ 0, 4, 8}, // 1. block forward
{ 6, 2, 10}, // 1. block backward
{12, 14, 16}}; // 1. block bi-directional
int mbtype, pdir0, pdir1;
if (img->type!=B_SLICE)
{
if (currMB->mb_type==I8MB ||currMB->mb_type==I4MB)
return (img->type==I_SLICE ? 0 : 6);
else if (currMB->mb_type==I16MB) return (img->type==I_SLICE ? 0 : 6) + img->i16offset;
else if (currMB->mb_type==IPCM) return (img->type==I_SLICE ? 25 : 31);
else if (currMB->mb_type==P8x8)
{
if (img->currentSlice->symbol_mode==CAVLC
&& ZeroRef (currMB)) return 5;
else return 4;
}
else return currMB->mb_type;
}
else
{
mbtype = currMB->mb_type;
pdir0 = currMB->b8pdir[0];
pdir1 = currMB->b8pdir[3];
if (mbtype==0) return 0;
else if (mbtype==I4MB || mbtype==I8MB) return 23;
else if (mbtype==I16MB) return 23 + img->i16offset;
else if (mbtype==IPCM) return 48;
else if (mbtype==P8x8) return 22;
else if (mbtype==1) return dir1offset[pdir0];
else if (mbtype==2) return 4 + dir2offset[pdir0][pdir1];
else return 5 + dir2offset[pdir0][pdir1];
}
}
/*!
************************************************************************
* \brief
* Writes 4x4 intra prediction modes for a macroblock
************************************************************************
*/
int writeIntra4x4Modes(Macroblock *currMB)
{
int i;
SyntaxElement se;
int *bitCount = currMB->bitcounter;
Slice *currSlice = img->currentSlice;
const int *partMap = assignSE2partition[params->partition_mode];
DataPartition *dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
int rate = 0;
currMB->IntraChromaPredModeFlag = 1;
for(i=0;i<16;i++)
{
se.context = i;
se.value1 = currMB->intra_pred_modes[i];
se.value2 = 0;
#if TRACE
if (se.value1 < 0 )
snprintf(se.tracestring, TRACESTRING_SIZE, "Intra 4x4 mode = predicted (context: %d)",se.context);
else
snprintf(se.tracestring, TRACESTRING_SIZE, "Intra 4x4 mode = %3d (context: %d)",se.value1,se.context);
#endif
// set symbol type and function pointers
se.type = SE_INTRAPREDMODE;
// encode and update rate
writeIntraPredMode (&se, dataPart);
bitCount[BITS_COEFF_Y_MB]+=se.len;
rate += se.len;
}
return rate;
}
/*!
************************************************************************
* \brief
* Writes 8x8 intra prediction modes for a macroblock
************************************************************************
*/
int writeIntra8x8Modes(Macroblock *currMB)
{
int block8x8;
SyntaxElement se;
int *bitCount = currMB->bitcounter;
Slice *currSlice = img->currentSlice;
const int *partMap = assignSE2partition[params->partition_mode];
DataPartition *dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
int rate = 0;
currMB->IntraChromaPredModeFlag = 1;
for(block8x8 = 0;block8x8 < 16; block8x8 += 4)
{
se.context = block8x8;
se.value1 = currMB->intra_pred_modes8x8[block8x8];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -