📄 pred.c
字号:
#include"sim.h"static int roundtab[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};/********************************************************************** * * 函数名:P帧图像的预测 * 函数功能:P帧编码宏块的运动预测编码(普通模式和高级模式) * 函数输入:curr_image:当前帧图像 * prev_image:上一帧图像 * prev_ipol:上一帧内插图像 * x:宏块的位置(水平方位)
* y:宏块的位置(竖直方位)
* MV:运动向量
* PB:运动估计模式标志
* 函数返回值:编码宏块数据的指针 ***********************************************************************/MB_Structure *Predict_P(PictImage *curr_image, PictImage *prev_image, unsigned char *prev_ipol, int x, int y, MotionVector *MV[6][MBR+1][MBC+2], int PB){ int m,n; int curr[16][16]; int pred[16][16]; MotionVector *fr0,*fr1,*fr2,*fr3,*fr4; int sum, dx, dy; int xmb, ymb; MB_Structure *pred_error = (MB_Structure *)malloc(sizeof(MB_Structure)); xmb = x/MB_SIZE+1; ymb = y/MB_SIZE+1; fr0 = MV[0][ymb][xmb]; fr1 = MV[1][ymb][xmb]; fr2 = MV[2][ymb][xmb]; fr3 = MV[3][ymb][xmb]; fr4 = MV[4][ymb][xmb]; /* 找到当前帧的编码宏块 */ FindMB(x, y, curr_image->lum, curr); /* 利用半像素精度的运动向量寻找预测值 */ if (advanced) { FindPredOBMC(x, y, MV, prev_ipol, &pred[0][0], 0, PB); FindPredOBMC(x, y, MV, prev_ipol, &pred[0][8], 1, PB); FindPredOBMC(x, y, MV, prev_ipol, &pred[8][0], 2, PB); FindPredOBMC(x, y, MV, prev_ipol, &pred[8][8], 3, PB); } else FindPred(x, y, fr0, prev_ipol, &pred[0][0], 16, 0); /* 实际运动估计的预测 */ if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) { for (n = 0; n < MB_SIZE; n++) for (m = 0; m < MB_SIZE; m++) pred_error->lum[n][m] = (int)(curr[n][m] - pred[n][m]); dx = 2*fr0->x + fr0->x_half; dy = 2*fr0->y + fr0->y_half; dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 ); dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 ); DoPredChrom_P(x, y, dx, dy, curr_image, prev_image, pred_error); } else if (fr0->Mode == MODE_INTER4V) { for (n = 0; n < MB_SIZE; n++) for (m = 0; m < MB_SIZE; m++) pred_error->lum[n][m] = (int)(curr[n][m] - pred[n][m]); sum = 2*fr1->x + fr1->x_half + 2*fr2->x + fr2->x_half + 2*fr3->x + fr3->x_half + 2*fr4->x + fr4->x_half ; dx = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2); sum = 2*fr1->y + fr1->y_half + 2*fr2->y + fr2->y_half + 2*fr3->y + fr3->y_half + 2*fr4->y + fr4->y_half; dy = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2); DoPredChrom_P(x, y, dx, dy, curr_image, prev_image, pred_error); } else fprintf(stderr,"Illegal Mode in Predict_P (pred.c)\n"); return pred_error;}/**********************************************************************
*
* 函数名:B帧图像的预测
* 函数功能:在PB模式下B帧编码宏块的运动预测编码
* 函数输入:curr_image:当前帧图像
* prev_image:上一帧图像
* prev_ipol:上一帧内插图像
* x:宏块的位置(水平方位)
* y:宏块的位置(竖直方位)
* MV:运动向量
* recon_P:上一帧重构的P帧编码宏块
* TRD:重构宏块的位置(水平方位)
* TRB:重构宏块的位置(竖直方位)
* 函数返回值:运动估计后编码宏块差分数据的指针
***********************************************************************/MB_Structure *Predict_B(PictImage *curr_image, PictImage *prev_image, unsigned char *prev_ipol,int x, int y, MotionVector *MV[5][MBR+1][MBC+2], MB_Structure *recon_P, int TRD,int TRB){ int i,j,k; int dx, dy, sad, sad_min=INT_MAX, curr[16][16], bdx=0, bdy=0; MB_Structure *p_err = (MB_Structure *)malloc(sizeof(MB_Structure)); MB_Structure *pred = (MB_Structure *)malloc(sizeof(MB_Structure)); MotionVector *f[5]; int xvec, yvec, mvx, mvy; for (k = 0; k <= 4; k++) f[k] = MV[k][y/MB_SIZE+1][x/MB_SIZE+1]; /* 找到当前帧的编码宏块 */ FindMB(x, y, curr_image->lum, curr); if (f[0]->Mode == MODE_INTER4V) { /* INTER4V模式 */ /* 计算前向预测 */ /* 亮度分量 */ for (j = -DEF_PBDELTA_WIN; j <= DEF_PBDELTA_WIN; j++) { for (i = -DEF_PBDELTA_WIN; i <= DEF_PBDELTA_WIN; i++) { FindForwLumPredPB(prev_ipol, x, y, f[1], &pred->lum[0][0], TRD, TRB, i, j, 8, 0); FindForwLumPredPB(prev_ipol, x, y, f[2], &pred->lum[0][8], TRD, TRB, i, j, 8, 1); FindForwLumPredPB(prev_ipol, x, y, f[3], &pred->lum[8][0], TRD, TRB, i, j, 8, 2); FindForwLumPredPB(prev_ipol, x, y, f[4], &pred->lum[8][8], TRD, TRB, i, j, 8, 3); sad = SAD_MB_integer(&curr[0][0],&pred->lum[0][0], 16,INT_MAX); if (i == 0 && j == 0) sad -= PREF_PBDELTA_NULL_VEC; if (sad < sad_min) { sad_min = sad; bdx = i; bdy = j; } } } FindForwLumPredPB(prev_ipol,x,y,f[1],&pred->lum[0][0],TRD,TRB,bdx,bdy,8,0); FindForwLumPredPB(prev_ipol,x,y,f[2],&pred->lum[0][8],TRD,TRB,bdx,bdy,8,1); FindForwLumPredPB(prev_ipol,x,y,f[3],&pred->lum[8][0],TRD,TRB,bdx,bdy,8,2); FindForwLumPredPB(prev_ipol,x,y,f[4],&pred->lum[8][8],TRD,TRB,bdx,bdy,8,3); /* 色度分量的运动向量 */ xvec = yvec = 0; for (k = 1; k <= 4; k++) { xvec += TRB*(2*f[k]->x + f[k]->x_half)/TRD + bdx; yvec += TRB*(2*f[k]->y + f[k]->y_half)/TRD + bdy; } /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindChromBlock_P(x, y, dx, dy, prev_image, pred); /* 计算双向运动估计 */ FindBiDirLumPredPB(&recon_P->lum[0][0], f[1], &pred->lum[0][0], TRD, TRB, bdx, bdy, 0, 0); FindBiDirLumPredPB(&recon_P->lum[0][8], f[2], &pred->lum[0][8], TRD, TRB, bdx, bdy, 1, 0); FindBiDirLumPredPB(&recon_P->lum[8][0], f[3], &pred->lum[8][0], TRD, TRB, bdx, bdy, 0, 1); FindBiDirLumPredPB(&recon_P->lum[8][8], f[4], &pred->lum[8][8], TRD, TRB, bdx, bdy, 1, 1); /* 色度分量的运动向量 */ xvec = yvec = 0; for (k = 1; k <= 4; k++) { mvx = 2*f[k]->x + f[k]->x_half; mvy = 2*f[k]->y + f[k]->y_half; xvec += bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx; yvec += bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy; } /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindBiDirChrPredPB(recon_P, dx, dy, pred); } else { /* 帧间和INTER_Q模式 */ /* 计算前向运动估计 */ for (j = -DEF_PBDELTA_WIN; j <= DEF_PBDELTA_WIN; j++) { for (i = -DEF_PBDELTA_WIN; i <= DEF_PBDELTA_WIN; i++) { dx = i; dy = j; /* 宏块边缘PB帧的向量差置为0 */ if (!mv_outside_frame) { if (x == 0) dx = 0; if (x == pels - MB_SIZE) dx = 0; if (y == 0) dy = 0; if (y == lines - MB_SIZE) dy = 0; } if (f[0]->Mode == MODE_INTRA || f[0]->Mode == MODE_INTRA_Q) { dx = dy = 0; } if (f[0]->x == 0 && f[0]->y == 0 && f[0]->x_half == 0 && f[0]->y_half == 0) { dx = dy = 0; } FindForwLumPredPB(prev_ipol, x, y, f[0], &pred->lum[0][0], TRD, TRB, dx, dy, 16, 0); sad = SAD_MB_integer(&curr[0][0],&pred->lum[0][0], 16, INT_MAX); if (i == 0 && j == 0) sad -= PREF_PBDELTA_NULL_VEC; if (sad < sad_min) { sad_min = sad; bdx = dx; bdy = dy; } } } FindForwLumPredPB(prev_ipol,x,y,f[0],&pred->lum[0][0],TRD,TRB, bdx,bdy,16,0); xvec = 4 * (TRB*(2*f[0]->x + f[0]->x_half) / TRD + bdx); yvec = 4 * (TRB*(2*f[0]->y + f[0]->y_half) / TRD + bdy); /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindChromBlock_P(x, y, dx, dy, prev_image, pred); /* 计算双向运动估计 */ FindBiDirLumPredPB(&recon_P->lum[0][0], f[0], &pred->lum[0][0], TRD, TRB, bdx, bdy, 0, 0); FindBiDirLumPredPB(&recon_P->lum[0][8], f[0], &pred->lum[0][8], TRD, TRB, bdx, bdy, 1, 0); FindBiDirLumPredPB(&recon_P->lum[8][0], f[0], &pred->lum[8][0], TRD, TRB, bdx, bdy, 0, 1); FindBiDirLumPredPB(&recon_P->lum[8][8], f[0], &pred->lum[8][8], TRD, TRB, bdx, bdy, 1, 1); /* 色度运动向量 */ mvx = 2*f[0]->x + f[0]->x_half; xvec = bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx; xvec *= 4; mvy = 2*f[0]->y + f[0]->y_half; yvec = bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy; yvec *= 4; /* 色度运动向量 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindBiDirChrPredPB(recon_P, dx, dy, pred); } /* 存放delta值 */ MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x = bdx; /* 半像素精度 */ MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y = bdy; MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x_half = 0; MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y_half = 0; /* 完成最后的运动估计 */ for (j = 0; j < MB_SIZE; j++) for (i = 0; i < MB_SIZE; i++) p_err->lum[j][i] = *(curr_image->lum+x+i + (y+j)*pels) - pred->lum[j][i]; y >>= 1; x >>= 1; for (j = 0; j < MB_SIZE>>1; j++) for (i = 0; i < MB_SIZE>>1; i++) { p_err->Cr[j][i] = *(curr_image->Cr+x+i + (y+j)*cpels) - pred->Cr[j][i]; p_err->Cb[j][i] = *(curr_image->Cb+x+i + (y+j)*cpels) - pred->Cb[j][i]; } free(pred); return p_err;}/**********************************************************************
*
* 函数名:MB_Recon_B
* 函数功能:在PB模式下重构B帧编码宏块
* 函数输入:curr_image:当前帧图像
* prev_image:上一帧图像
* prev_ipol:上一帧内插图像
* x:宏块的位置(水平方位)
* y:宏块的位置(竖直方位)
* MV:运动向量
* recon_P:上一帧重构的编码宏块
* TRD:重构宏块的位置(水平方位)
* TRB:重构宏块的位置(竖直方位)
* 函数返回值:重构编码宏块数据的指针
***********************************************************************/
MB_Structure *MB_Recon_B(PictImage *prev_image, MB_Structure *diff, unsigned char *prev_ipol,int x, int y, MotionVector *MV[5][MBR+1][MBC+2], MB_Structure *recon_P,int TRD, int TRB){ int i,j,k; int dx, dy, bdx, bdy, mvx, mvy, xvec, yvec; MB_Structure *recon_B = (MB_Structure *)malloc(sizeof(MB_Structure)); MB_Structure *pred = (MB_Structure *)malloc(sizeof(MB_Structure)); MotionVector *f[5]; for (k = 0; k <= 4; k++) f[k] = MV[k][y/MB_SIZE+1][x/MB_SIZE+1]; bdx = MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x; bdy = MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y; if (f[0]->Mode == MODE_INTER4V) { /* INTER4V模式 */ /* 计算前向运动估计 */ /* 亮度分量 */ FindForwLumPredPB(prev_ipol,x,y,f[1],&pred->lum[0][0],TRD,TRB,bdx,bdy,8,0); FindForwLumPredPB(prev_ipol,x,y,f[2],&pred->lum[0][8],TRD,TRB,bdx,bdy,8,1); FindForwLumPredPB(prev_ipol,x,y,f[3],&pred->lum[8][0],TRD,TRB,bdx,bdy,8,2); FindForwLumPredPB(prev_ipol,x,y,f[4],&pred->lum[8][8],TRD,TRB,bdx,bdy,8,3); /* 色度运动向量 */ xvec = yvec = 0; for (k = 1; k <= 4; k++) { xvec += TRB*(2*f[k]->x + f[k]->x_half)/TRD + bdx; yvec += TRB*(2*f[k]->y + f[k]->y_half)/TRD + bdy; } /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindChromBlock_P(x, y, dx, dy, prev_image, pred); /* 计算双向运动估计 */ FindBiDirLumPredPB(&recon_P->lum[0][0], f[1], &pred->lum[0][0], TRD, TRB, bdx, bdy, 0, 0); FindBiDirLumPredPB(&recon_P->lum[0][8], f[2], &pred->lum[0][8], TRD, TRB, bdx, bdy, 1, 0); FindBiDirLumPredPB(&recon_P->lum[8][0], f[3], &pred->lum[8][0], TRD, TRB, bdx, bdy, 0, 1); FindBiDirLumPredPB(&recon_P->lum[8][8], f[4], &pred->lum[8][8], TRD, TRB, bdx, bdy, 1, 1); /* 色度分量的运动向量 */ xvec = yvec = 0; for (k = 1; k <= 4; k++) { mvx = 2*f[k]->x + f[k]->x_half; mvy = 2*f[k]->y + f[k]->y_half; xvec += bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx; yvec += bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy; } /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindBiDirChrPredPB(recon_P, dx, dy, pred); } else { /* 帧间或INTER_Q模式 */ /* 计算前向运动估计 */ FindForwLumPredPB(prev_ipol,x,y,f[0],&pred->lum[0][0],TRD,TRB, bdx,bdy,16,0); xvec = 4 * (TRB*(2*f[0]->x + f[0]->x_half) / TRD + bdx); yvec = 4 * (TRB*(2*f[0]->y + f[0]->y_half) / TRD + bdy); /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindChromBlock_P(x, y, dx, dy, prev_image, pred); /* 计算双向运动估计 */ FindBiDirLumPredPB(&recon_P->lum[0][0], f[0], &pred->lum[0][0], TRD, TRB, bdx, bdy, 0, 0); FindBiDirLumPredPB(&recon_P->lum[0][8], f[0], &pred->lum[0][8], TRD, TRB, bdx, bdy, 1, 0); FindBiDirLumPredPB(&recon_P->lum[8][0], f[0], &pred->lum[8][0], TRD, TRB, bdx, bdy, 0, 1); FindBiDirLumPredPB(&recon_P->lum[8][8], f[0], &pred->lum[8][8], TRD, TRB, bdx, bdy, 1, 1); /* 色度分量的运动向量 */ mvx = 2*f[0]->x + f[0]->x_half; xvec = bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx; xvec *= 4; mvy = 2*f[0]->y + f[0]->y_half; yvec = bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy; yvec *= 4; /* /* 根据表7-17得到近似值 */ dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2); dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2); FindBiDirChrPredPB(recon_P, dx, dy, pred); } /* 重构出P帧的编码宏块 */ for (j = 0; j < MB_SIZE; j++) for (i = 0; i < MB_SIZE; i++) recon_B->lum[j][i] = pred->lum[j][i] + diff->lum[j][i]; for (j = 0; j < MB_SIZE>>1; j++) for (i = 0; i < MB_SIZE>>1; i++) { recon_B->Cr[j][i] = pred->Cr[j][i] + diff->Cr[j][i]; recon_B->Cb[j][i] = pred->Cb[j][i] + diff->Cb[j][i]; } free(pred); return recon_B;}
/**********************************************************************
*
* 函数名:FindForwLumPredPB
* 函数功能:在PB模式下计算前向亮度分量的运动估计
* 函数输入:prev_ipol:上一帧内插图像
* x_cur:当前帧宏块的位置(水平方位)
* y_cur:当前帧宏块的位置(竖直方位)
* fr:运动向量
* pred:预测宏块的数据指针
* TRD:重构宏块的位置(水平方位)
* TRB:重构宏块的位置(竖直方位)
* 函数返回值:重构编码宏块数据的指针,宏块的位置以及MV数据
***********************************************************************/
void FindForwLumPredPB(unsigned char *prev_ipol, int x_curr, int y_curr, MotionVector *fr, int *pred, int TRD, int TRB, int bdx, int bdy, int bs, int comp){ int i,j; int xvec,yvec,lx; lx = (mv_outside_frame ? pels + (long_vectors?64:32) : pels); /* 亮度分量 */ xvec = (TRB)*(2*fr->x + fr->x_half)/TRD + bdx; yvec = (TRB)*(2*fr->y + fr->y_half)/TRD + bdy; x_curr += ((comp&1)<<3); y_curr += ((comp&2)<<2); for (j = 0; j < bs; j++) { for (i = 0; i < bs; i++) { *(pred+i+j*16) = *(prev_ipol + (i+x_curr)*2 + xvec + ((j+y_curr)*2 + yvec)*lx*2); } } return;}/**********************************************************************
*
* 函数名:FindBiDirLumPredPB
* 函数功能:在PB模式下寻找双向亮度信息的预测值
* 函数输入:recon_P:重构恢复出来的P帧编码宏块
* fr:宏块的运动向量
* pred:预测宏块的数据指针
* TRD:重构宏块的位置(水平方位)
* TRB:重构宏块的位置(竖直方位)*
***********************************************************************/void FindBiDirLumPredPB(int *recon_P, MotionVector *fr, int *pred, int TRD, int TRB, int bdx, int bdy, int nh, int nv){ int xstart,xstop,ystart,ystop; int xvec,yvec, mvx, mvy; mvx = 2*fr->x + fr->x_half; mvy = 2*fr->y + fr->y_half; xvec = (bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx); yvec = (bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -