CodeInter.cpp
资源名称:263.rar [点击查看]
上传用户:szklck
上传日期:2007-01-22
资源大小:925k
文件大小:12k
源码类别:
图形图像处理
开发平台:
Visual C++
- #include"stdafx.h"
- #include"Global.h"
- /**********************************************************************
- *
- * Name: CodeOneInter
- * Description: code one image normally or two images
- * as a PB-frame (CodeTwoPB and CodeOnePred merged)
- *
- * Input: pointer to image, prev_image, prev_recon, Q
- *
- * Returns: pointer to reconstructed image
- * Side effects: memory is allocated to recon image
- *
- ************************************************************************/
- void CodeOneInter(PictImage *prev,PictImage *curr,
- PictImage *pr,PictImage *curr_recon,
- int QP, int frameskip, Bits *bits, Pict *pic)
- {
- ZeroBits(bits);
- unsigned char *prev_ipol,*pi,*orig_lum;
- PictImage *prev_recon=NULL;
- MotionVector *MV[6][MBR+1][MBC+2];
- MotionVector ZERO = {0,0,0,0,0};
- int i,j,k;
- int newgob,Mode;
- int *qcoeff_P;
- int CBP, CBPB=0;
- MB_Structure *recon_data_P;
- MB_Structure *diff;
- /* 缓冲器控制变量 */
- float QP_cumulative = (float)0.0;
- int abs_mb_num = 0, QuantChangePostponed = 0;
- int QP_new, QP_prev, dquant, QP_xmitted=QP;
- QP_new = QP_xmitted = QP_prev = QP; /* 复制旧QP */
- /* 图象插值 */
- if(!mv_outside_frame)
- {
- pi = InterpolateImage(pr->lum,pels,lines);
- prev_ipol = pi;
- prev_recon = pr;
- orig_lum = prev->lum;
- }
- /* 为每个编码块标记MV */
- for (i = 1; i < (pels>>4)+1; i++) {
- for (k = 0; k < 6; k++) {
- MV[k][0][i] = (MotionVector *)malloc(sizeof(MotionVector));
- MarkVec(MV[k][0][i]);
- }
- MV[0][0][i]->Mode = MODE_INTRA;
- }
- /* 超出图象边界的MV置为0 */
- for (i = 0; i < (lines>>4)+1; i++) {
- for (k = 0; k < 6; k++) {
- MV[k][i][0] = (MotionVector *)malloc(sizeof(MotionVector));
- ZeroVec(MV[k][i][0]);
- MV[k][i][(pels>>4)+1] = (MotionVector *)malloc(sizeof(MotionVector));
- ZeroVec(MV[k][i][(pels>>4)+1]);
- }
- MV[0][i][0]->Mode = MODE_INTRA;
- MV[0][i][(pels>>4)+1]->Mode = MODE_INTRA;
- }
- /* 整数和半象素运动估值 */
- MotionEstimatePicture(curr->lum, prev_recon->lum, prev_ipol,
- pic->seek_dist, MV, pic->use_gobsync);
- #ifndef OFFLINE_RATE_CONTROL
- if (pic->bit_rate != 0) {
- /* 初始化码率控制 */
- QP_new = InitializeQuantizer(PCT_INTER, (float)pic->bit_rate,
- (pic->PB ? pic->target_frame_rate/2 : pic->target_frame_rate),
- pic->QP_mean);
- QP_xmitted = QP_prev = QP_new;
- }
- else {
- QP_new = QP_xmitted = QP_prev = QP; /* 复制旧 QP */
- }
- #else
- QP_new = QP_xmitted = QP_prev = QP; /* 复制旧 QP */
- #endif
- dquant = 0;
- for ( j = 0; j < lines/MB_SIZE; j++) {
- #ifndef OFFLINE_RATE_CONTROL
- if (pic->bit_rate != 0) {
- AddBitsPicture(bits);
- /* 更新QP */
- QP_new = UpdateQuantizer(abs_mb_num, pic->QP_mean, PCT_INTER,
- (float)pic->bit_rate, pels/MB_SIZE, lines/MB_SIZE,
- bits->total);
- }
- #endif
- newgob = 0;
- if (j == 0) {
- pic->QUANT = QP;
- bits->header += CountBitsPicture(pic);//计算图象层码字
- }
- else if (pic->use_gobsync && j%pic->use_gobsync == 0) {
- bits->header += CountBitsSlice(j,QP); //输出GOB同步头
- newgob = 1;
- }
- for ( i = 0; i < pels/MB_SIZE; i++) {
- /* 更新dquant */
- dquant = QP_new - QP_prev;
- if (dquant != 0 && i != 0 && MV[0][j+1][i+1]->Mode == MODE_INTER4V) {
- dquant = 0;
- QP_xmitted = QP_prev;
- QuantChangePostponed = 1;
- }
- else {
- QP_xmitted = QP_new;
- QuantChangePostponed = 0;
- }
- if (dquant > 2) { dquant = 2; QP_xmitted = QP_prev + dquant;}
- if (dquant < -2) { dquant = -2; QP_xmitted = QP_prev + dquant;}
- pic->DQUANT = dquant;
- /* 当dquant != 0,修改宏块类型 (例如 MODE_INTER -> MODE_INTER_Q) */
- Mode = ModifyMode(MV[0][j+1][i+1]->Mode,pic->DQUANT);
- MV[0][j+1][i+1]->Mode = Mode;
- pic->MB = i + j * (pels/MB_SIZE);
- if (Mode == MODE_INTER || Mode == MODE_INTER_Q || Mode==MODE_INTER4V) {
- /* 预测P-宏块 */
- diff = Predict_P(curr,prev_recon,prev_ipol,
- i*MB_SIZE,j*MB_SIZE,MV,pic->PB);
- }
- else {
- diff = (MB_Structure *)malloc(sizeof(MB_Structure));
- FillLumBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);//写亮度图像 curr:图像数据 diff:宏块树组
- FillChromBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);//写色度图像
- }
- /* P或INTRA宏块 */
- qcoeff_P = MB_Encode(diff, QP_xmitted, Mode); //对宏块数据(P块为残差数据)进行DCT变换量化
- CBP = FindCBP(qcoeff_P, Mode, 64);
- if (CBP == 0 && (Mode == MODE_INTER || Mode == MODE_INTER_Q))
- ZeroMBlock(diff); //宏块数据设为0
- else
- MB_Decode(qcoeff_P, diff, QP_xmitted, Mode);//反变换
- recon_data_P = MB_Recon_P(prev_recon, prev_ipol,diff,i*MB_SIZE,j*MB_SIZE,MV,pic->PB);//重建P图象
- Clip(recon_data_P); //使 0<=recon_data_P<=255
- free(diff);
- if(pic->PB==0)
- ZeroVec(MV[5][j+1][i+1]); //PB帧矢量差置为0
- if ((CBP==0) && (CBPB==0) &&
- (EqualVec(MV[0][j+1][i+1],&ZERO)) &&
- (EqualVec(MV[5][j+1][i+1],&ZERO)) &&
- (Mode == MODE_INTER || Mode == MODE_INTER_Q)) {
- /* 当 CBP 和 CBPB 为0, 16x16 运动矢量为0,PB矢量差为0,
- 并且编码模式为MODE_INTER或MODE_INTER_Q,跳过该宏块编码*/
- if (!syntax_arith_coding)
- CountBitsMB(Mode,1,CBP,CBPB,pic,bits);//输出宏块层信息
- }
- else { /* 正常编码宏块 */
- if (!syntax_arith_coding) { /* VLC */
- CountBitsMB(Mode,0,CBP,CBPB,pic,bits);
- if (Mode == MODE_INTER || Mode == MODE_INTER_Q) {
- bits->no_inter++;
- CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);//输出运动矢量数据
- }
- else if (Mode == MODE_INTER4V) {
- bits->no_inter4v++;
- CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);
- }
- else {
- /* MODE_INTRA 或 MODE_INTRA_Q */
- bits->no_intra++;
- if (pic->PB)
- CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);
- }
- if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
- CountBitsCoeff(qcoeff_P, Mode, CBP, bits, 64);//输出系数
- } // end VLC
- QP_prev = QP_xmitted;
- }//end Normal MB
- abs_mb_num++;
- QP_cumulative += QP_xmitted;
- ReconImage(i,j,recon_data_P,curr_recon);//重建图象
- free(recon_data_P);
- free(qcoeff_P);
- }//end for i
- }//end for j
- pic->QP_mean = QP_cumulative/(float)abs_mb_num;
- /* 释放内存 */
- free(pi);
- for (j = 0; j < (lines>>4)+1; j++)
- for (i = 0; i < (pels>>4)+2; i++)
- for (k = 0; k < 6; k++)
- free(MV[k][j][i]);
- return;
- }
- void ZeroVec(MotionVector *MV)
- {
- MV->x = 0;
- MV->y = 0;
- MV->x_half = 0;
- MV->y_half = 0;
- return;
- }
- void MarkVec(MotionVector *MV)
- {
- MV->x = NO_VEC;
- MV->y = NO_VEC;
- MV->x_half = 0;
- MV->y_half = 0;
- return;
- }
- void CopyVec(MotionVector *MV2, MotionVector *MV1)
- {
- MV2->x = MV1->x;
- MV2->x_half = MV1->x_half;
- MV2->y = MV1->y;
- MV2->y_half = MV1->y_half;
- return;
- }
- int EqualVec(MotionVector *MV2, MotionVector *MV1)
- {
- if (MV1->x != MV2->x)
- return 0;
- if (MV1->y != MV2->y)
- return 0;
- if (MV1->x_half != MV2->x_half)
- return 0;
- if (MV1->y_half != MV2->y_half)
- return 0;
- return 1;
- }
- unsigned char *InterpolateImage(unsigned char *image, int width, int height)
- {
- unsigned char *ipol_image, *ii, *oo;
- int i,j;
- ipol_image = (unsigned char *)malloc(sizeof(char)*width*height*4);
- ii = ipol_image;
- oo = image;
- /* main image */
- for (j = 0; j < height-1; j++) {
- for (i = 0; i < width-1; i++) {
- *(ii + (i<<1)) = *(oo + i);
- *(ii + (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
- *(ii + (i<<1)+(width<<1)) = (unsigned char)((*(oo + i) + *(oo + i + width) + 1)>>1);
- *(ii + (i<<1)+1+(width<<1)) = (unsigned char)((*(oo+i) + *(oo+i+1) +
- *(oo+i+width) + *(oo+i+1+width) + 2)>>2);
- }
- /* last pels on each line */
- *(ii+ (width<<1) - 2) = *(oo + width - 1);
- *(ii+ (width<<1) - 1) = *(oo + width - 1);
- *(ii+ (width<<1)+ (width<<1)-2) = (unsigned char)((*(oo+width-1)+*(oo+width+width-1)+1)>>1);
- *(ii+ (width<<1)+ (width<<1)-1) = (unsigned char)((*(oo+width-1)+*(oo+width+width-1)+1)>>1);
- ii += (width<<2);
- oo += width;
- }
- /* last lines */
- for (i = 0; i < width-1; i++) {
- *(ii+ (i<<1)) = *(oo + i);
- *(ii+ (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
- *(ii+ (width<<1)+ (i<<1)) = *(oo + i);
- *(ii+ (width<<1)+ (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
- }
- /* bottom right corner pels */
- *(ii + (width<<1) - 2) = *(oo + width -1);
- *(ii + (width<<1) - 1) = *(oo + width -1);
- *(ii + (width<<2) - 2) = *(oo + width -1);
- *(ii + (width<<2) - 1) = *(oo + width -1);
- return ipol_image;
- }
- void MotionEstimatePicture(unsigned char *curr, unsigned char *prev,
- unsigned char *prev_ipol, int seek_dist,
- MotionVector *MV[6][MBR+1][MBC+2], int gobsync)
- {
- int i,j,k;
- int pmv0,pmv1,xoff,yoff;
- int curr_mb[16][16];
- int sad8 = INT_MAX, sad16, sad0;
- int newgob;
- MotionVector *f0,*f1,*f2,*f3,*f4;
- /* 运动估计并存储结果MV */
- for ( j = 0; j < lines/MB_SIZE; j++) {
- newgob = 0;
- if (gobsync && j%gobsync == 0) {
- newgob = 1;
- }
- for ( i = 0; i < pels/MB_SIZE; i++) {
- for (k = 0; k < 6; k++)
- MV[k][j+1][i+1] = (MotionVector *)malloc(sizeof(MotionVector));
- /* 整象素搜索 */
- f0 = MV[0][j+1][i+1];
- f1 = MV[1][j+1][i+1];
- f2 = MV[2][j+1][i+1];
- f3 = MV[3][j+1][i+1];
- f4 = MV[4][j+1][i+1];
- FindPMV(MV,i+1,j+1,&pmv0,&pmv1,0,newgob,0);
- if (long_vectors) {
- xoff = pmv0/2; /* 总是能被2整除 */
- yoff = pmv1/2;
- }
- else {
- xoff = yoff = 0;
- }
- MotionEstimation(curr, prev, i*MB_SIZE, j*MB_SIZE,
- xoff, yoff, seek_dist, MV, &sad0);
- sad16 = f0->min_error;
- if (advanced)
- sad8 = f1->min_error + f2->min_error + f3->min_error + f4->min_error;
- f0->Mode = ChooseMode(curr,i*MB_SIZE,j*MB_SIZE, mmin(sad8,sad16));
- /* 半象素精度搜索 */
- if (f0->Mode != MODE_INTRA) {
- FindMB(i*MB_SIZE,j*MB_SIZE ,curr, curr_mb);//当前宏块放入curr_mb
- FindHalfPel(i*MB_SIZE,j*MB_SIZE,f0, prev_ipol, &curr_mb[0][0],16,0);
- sad16 = f0->min_error;
- if (advanced) {
- FindHalfPel(i*MB_SIZE,j*MB_SIZE,f1, prev_ipol, &curr_mb[0][0],8,0);
- FindHalfPel(i*MB_SIZE,j*MB_SIZE,f2, prev_ipol, &curr_mb[0][8],8,1);
- FindHalfPel(i*MB_SIZE,j*MB_SIZE,f3, prev_ipol, &curr_mb[8][0],8,2);
- FindHalfPel(i*MB_SIZE,j*MB_SIZE,f4, prev_ipol, &curr_mb[8][8],8,3);
- sad8 = f1->min_error +f2->min_error +f3->min_error +f4->min_error;
- sad8 += PREF_16_VEC;
- /* 选择0运动矢量, 基于8x8或16x16的运动矢量 */
- if (sad0 < sad8 && sad0 < sad16) {
- f0->x = f0->y = 0;
- f0->x_half = f0->y_half = 0;
- }
- else {
- if (sad8 < sad16)
- f0->Mode = MODE_INTER4V;
- }
- }
- else {
- /* 选择0运动矢量或基于16x16的运动矢量 */
- if (sad0 < sad16) {
- f0->x = f0->y = 0;
- f0->x_half = f0->y_half = 0;
- }
- }
- }
- else
- for (k = 0; k < 5; k++)
- ZeroVec(MV[k][j+1][i+1]);
- }
- }
- return;
- }
- void ZeroMBlock(MB_Structure *data)
- {
- int n;
- register int m;
- for (n = 0; n < MB_SIZE; n++)
- for (m = 0; m < MB_SIZE; m++)
- data->lum[n][m] = 0;
- for (n = 0; n < (MB_SIZE>>1); n++)
- for (m = 0; m < (MB_SIZE>>1); m++) {
- data->Cr[n][m] = 0;
- data->Cb[n][m] = 0;
- }
- return;
- }
English
