www.pudn.com > h263_.rar > Getpic.cpp
// Getpic.cpp: implementation of the CGetpic class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "视频编解码器.h"
#include "Getpic.h"
#include "indices.h"
#include "sactbls.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define sign(a) ((a) < 0 ? -1 : 1)
#define mmax(a, b) ((a) > (b) ? (a) : (b))
#define mmin(a, b) ((a) < (b) ? (a) : (b))
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int MV[2][5][MBR_MAX+1][MBC_MAX+2];
int modemap[MBR_MAX+1][MBC_MAX+2];
extern int mv_outside_frame;
extern unsigned char *edgeframe[3], *edgeframeorig[3], *exnewframe[3],*bframe[3];
extern unsigned char *newframe[3],*oldrefframe[3],*refframe[3];
extern int horizontal_size,vertical_size,mb_width,mb_height;
extern int coded_picture_width, coded_picture_height,pb_frame;
extern int chrom_width,chrom_height,expand,outtype,newgob;
extern int MBC,MBR,syntax_arith_coding,quiet,quant,trace,fault,tr_framenum;
extern int trb,trd,blk_cnt,pict_type,adv_pred_mode,long_vectors;
extern unsigned char *clp;
extern ldecode *ld;
CGetpic::CGetpic()
{
}
CGetpic::~CGetpic()
{
}
void CGetpic::getpicture(int *framenum)
{
int i;
unsigned char *tmp;
for (i=0; i<3; i++)
{
tmp = oldrefframe[i];
oldrefframe[i] = refframe[i];
refframe[i] = tmp;
newframe[i] = refframe[i];
}
//高级预测模式
if (mv_outside_frame && *framenum > 0)
{
make_edge_image(oldrefframe[0],edgeframe[0],coded_picture_width,
coded_picture_height,32);
make_edge_image(oldrefframe[1],edgeframe[1],chrom_width, chrom_height,16);
make_edge_image(oldrefframe[2],edgeframe[2],chrom_width, chrom_height,16);
}
//得到图像的块数据
getMBs(*framenum);
if (pb_frame)
{
if (expand && outtype == T_X11)//扩张模式 得到图像时间上的分辨率
{ //计算插值图像 Y U V
interpolate_image(bframe[0], exnewframe[0], coded_picture_width, coded_picture_height);
interpolate_image(bframe[1], exnewframe[1], chrom_width, chrom_height);
interpolate_image(bframe[2], exnewframe[2], chrom_width, chrom_height);
//存储变换后的图像
m_store.storeframe(exnewframe, *framenum);
}
else
m_store.storeframe(bframe,*framenum);
*framenum += pb_frame;
#ifdef USE_TIME
if (framerate > 0)
doframerate();
#endif
}//end of(pb_frame)
if (expand && outtype == T_X11)
{ //计算插值图像 增加时间上的分辨率
interpolate_image(newframe[0], exnewframe[0],
coded_picture_width, coded_picture_height);
interpolate_image(newframe[1], exnewframe[1],
chrom_width, chrom_height);
interpolate_image(newframe[2], exnewframe[2],
chrom_width, chrom_height);
//存储变换后的图像文件
m_store.storeframe(exnewframe, *framenum);
}
else
m_store.storeframe(newframe,*framenum);
}
/*****************************************************************************/
void CGetpic::getMBs(int framenum)
{
int comp;
int MBA, MBAmax;
int bx, by;
CString outshow;
int COD=0,MCBPC, CBPY, CBP=0, CBPB=0, MODB=0, Mode=0, DQUANT;
int COD_index, CBPY_index, MODB_index, DQUANT_index, MCBPC_index;
int INTRADC_index, YCBPB_index, UVCBPB_index, mvdbx_index, mvdby_index;
int mvx, mvy, mvy_index, mvx_index, pmv0, pmv1, xpos, ypos, gob, i,k;
int mvdbx=0, mvdby=0, pmvdbx, pmvdby, gfid, YCBPB, UVCBPB, gobheader_read;
int startmv,stopmv,offset,bsize,last_done=0,pCBP=0,pCBPB=0,pCOD=0;
int DQ_tab[4] = {-1,-2,1,2};
short *bp;
// 每帧图象的宏块数
MBAmax = mb_width*mb_height;
MBA = 0; // 宏块标志
newgob = 0;
//初始化图像边上的宏块的运动矢量
// 1 标记图象上边沿MV
for (i = 1; i < MBC+1; i++)
{
for (k = 0; k < 5; k++)
{
MV[0][k][0][i] = NO_VEC;
MV[1][k][0][i] = NO_VEC;
}
modemap[0][i] = MODE_INTRA;
}
// 2 标记图象边沿的MV为0
for (i = 0; i < MBR+1; i++)
{
for (k = 0; k < 5; k++)
{
MV[0][k][i][0] = 0;
MV[1][k][i][0] = 0;
MV[0][k][i][MBC+1] = 0;
MV[1][k][i][MBC+1] = 0;
}
modemap[i][0] = MODE_INTRA;
modemap[i][MBC+1] = MODE_INTRA;
}
fault = 0;
gobheader_read = 0;
//开始解码:
//1.先确定 COD
//2.根据COD的值决定是否解码块头信息Mcbpc,Cbpy,Mode,MV
//3.根据MV,Mode,CBPY,进行DCT变换恢复上一块的block数据(MBA-1)
//4.根据Mode,CBPY 从Huffman系数中得到(Run level,last)恢复当前块的DCT系数
for (;;)
{
if (trace)
{
outshow.Format("frame %d, MB %d\n",tr_framenum,MBA);
AfxMessageBox(outshow);
outshow.Empty();
}
resync:
if (fault)
{
outshow.Format("Warning: A Fault Condition Has Occurred - Resyncing!");
AfxMessageBox(outshow);
m_gethdr.startcode(); // sync on new startcode
fault = 0;
}
//确定是否是头信息
if (!(m_getbits.showbits(22)>>6))
{ // startcode
m_gethdr.startcode();
// 字节对齐,例如使用 PSTUF, GSTUF 或 ESTUF
if (m_getbits.showbits(22) == (32|SEC))
{ // EOS检测是否为序列结束标志
if (!(syntax_arith_coding && MBA < MBAmax))
return;
}
else if ((m_getbits.showbits(22) == PSC<<5) ) //PSC=1
{ // 新图像的开始
if (!(syntax_arith_coding && MBA < MBAmax))
return;
}
else
{
if (!(syntax_arith_coding && MBA%MBC))
{
if (syntax_arith_coding)
{ // SAC
gob = (m_getbits.showbits(22) & 31);
if (gob * mb_width != MBA)
goto finish_gob;
}
gob = m_gethdr.getheader() - 1;
if (gob > MBR)
{
if (!quiet)
AfxMessageBox("GN out of range!");
return ;
}
gfid = m_getbits.getbits(2); //GFID
quant = m_getbits.getbits(5);
if(trace)
{
outshow.Format("GQUANT: %d\n", quant);
AfxMessageBox(outshow);
}
xpos = 0;
ypos = gob;
MBA = ypos * mb_width;
newgob = 1;
gobheader_read = 1;
if (syntax_arith_coding)
m_sacode.decoder_reset();// init SAD buffer
}
}
}//end of(!(m_getbits.showbits(22)>>6))
finish_gob:
//开始解MB
if (!gobheader_read)
{
xpos = MBA%mb_width; //当前宏块的位置
ypos = MBA/mb_width;
if (xpos == 0 && ypos > 0)
newgob = 0;
}
else
gobheader_read = 0;
if (MBA>=MBAmax)
return; /* 所有宏块解码完毕 */
/*************************************************************/
// 1.确定COD
/*************************************************************/
read_cod:
if (syntax_arith_coding) //Sac code
{
if (pict_type == PCT_INTER)
{
COD_index = m_sacode.decode_a_symbol(cumf_COD);
COD = codtab[COD_index];
}
else
COD = 0;// I帧不使用COD, COD=0
}
else //比特编码
{
if(pict_type == PCT_INTER)
COD = m_getbits.showbits(1);
else
COD = 0; // I_picture-> not skipped
}
/******************************************************/
//2 根据COD确定是否要解码 其他块头信息(MCBPC CBPY MV)
/*****************************************************/
if(!COD) // COD == 0 --> not skipped
{
if (syntax_arith_coding)
{
if (pict_type == PCT_INTER)
{
MCBPC_index = m_sacode.decode_a_symbol(cumf_MCBPC);
MCBPC = mcbpctab[MCBPC_index];
}
else
{
MCBPC_index = m_sacode.decode_a_symbol(cumf_MCBPC_intra);
MCBPC = mcbpc_intratab[MCBPC_index];
}
if (trace)
{
outshow.Format("MCBPC Index: %d MCBPC: %d ",MCBPC_index, MCBPC);
AfxMessageBox(outshow);
}
}
else //DCT_Huff
{
if (pict_type == PCT_INTER)
m_getbits.flushbits(1); //flush COD bit
if (pict_type == PCT_INTRA)
MCBPC = m_getvlc.getMCBPCintra();
else
MCBPC = m_getvlc.getMCBPC();
}
if (fault)
goto resync;
if (MCBPC == -1) // stuffing
goto read_cod; //read next COD without advancing MB count
else
{ // normal MB data
Mode = MCBPC & 7;
//To Get MODB and CBPB
if (pb_frame)
{
CBPB = 0;
if (syntax_arith_coding)
{
MODB_index = m_sacode.decode_a_symbol(cumf_MODB);
MODB = modb_tab[MODB_index];
}
else
MODB = m_getvlc.getMODB();
if (MODB == PBMODE_CBPB_MVDB)
{
if (syntax_arith_coding)
{
for(i=0; i<4; i++)
{
YCBPB_index = m_sacode.decode_a_symbol(cumf_YCBPB);
YCBPB = ycbpb_tab[YCBPB_index];
CBPB |= (YCBPB << (6-1-i));
}
for(i=4; i<6; i++)
{
UVCBPB_index = m_sacode.decode_a_symbol(cumf_UVCBPB);
UVCBPB = uvcbpb_tab[UVCBPB_index];
CBPB |= (UVCBPB << (6-1-i));
}
}
else
CBPB = m_getbits.getbits(6);
if (trace)
{
outshow.Format("CBPB = %d\n",CBPB);
AfxMessageBox(outshow);
}
}
}//end of(pb_frame)
//解码 CBPY
if (syntax_arith_coding)
{
if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
{ // Intra
CBPY_index = m_sacode.decode_a_symbol(cumf_CBPY_intra);
CBPY = cbpy_intratab[CBPY_index];
}
else
{
CBPY_index = m_sacode.decode_a_symbol(cumf_CBPY);
CBPY = cbpytab[CBPY_index];
}
if (trace)
{
outshow.Format("CBPY Index: %d CBPY %d ",CBPY_index, CBPY);
AfxMessageBox(outshow);
}
}
else
CBPY = m_getvlc.getCBPY();
if (trace)
{
outshow.Format("CBPY = %d",CBPY);
AfxMessageBox(outshow);
}
// 解码 Mode and CBP
if(Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
if (!syntax_arith_coding) // Intra
CBPY = CBPY^15;
CBP = (CBPY << 2) | (MCBPC >> 4);
}
//
if(Mode == MODE_INTER4V && !adv_pred_mode)
if(!quiet)
AfxMessageBox("8x8 vectors not allowed in normal prediction mode\n");
//确定是否要解码DQUANT
if(Mode == MODE_INTER_Q || Mode == MODE_INTRA_Q)
{ // Read DQUANT if necessary
if (syntax_arith_coding)
{
DQUANT_index = m_sacode.decode_a_symbol(cumf_DQUANT);
DQUANT = dquanttab[DQUANT_index] - 2;
quant +=DQUANT;
if (trace)
{
outshow.Format("DQUANT Index: %d DQUANT %d \n",DQUANT_index, DQUANT);
AfxMessageBox(outshow);
}
}
else
{
DQUANT = m_getbits.getbits(2);
quant += DQ_tab[DQUANT];
}
if (trace)
{
outshow.Format("DQUANT:%d tab=%d ",DQUANT,DQ_tab[DQUANT]);
AfxMessageBox(outshow);
}
//调整量化因子到预定的范围内
if (quant > 31 || quant < 1)
{
if (!quiet)
AfxMessageBox("Quantizer out of range: clipping!");
quant = mmax(1,mmin(31,quant));
// could set fault-flag and resync here
}
}//end of (dquant decode)
//解码 motion vectors**********************************
if (Mode == MODE_INTER || Mode == MODE_INTER_Q
||Mode == MODE_INTER4V || pb_frame)
{
if (Mode == MODE_INTER4V)
{
startmv = 1;
stopmv = 4;
}
else
{
startmv = 0;
stopmv = 0;
}
for (k = startmv; k <= stopmv; k++)
{
if (syntax_arith_coding)
{
mvx_index = m_sacode.decode_a_symbol(cumf_MVD);
mvx = mvdtab[mvx_index];
mvy_index = m_sacode.decode_a_symbol(cumf_MVD);
mvy = mvdtab[mvy_index];
if (trace)
{
outshow.Format("mvx_index: %d mvy_index: %d \n", mvy_index, mvx_index);
AfxMessageBox(outshow);
}
}
else //Get Mv in HuffMan
{
mvx = m_getvlc.getTMNMV();
mvy = m_getvlc.getTMNMV();
}
pmv0 = find_pmv(xpos,ypos,k,0);
pmv1 = find_pmv(xpos,ypos,k,1);
mvx = motion_decode(mvx, pmv0);
mvy = motion_decode(mvy, pmv1);
if (trace)
{
outshow.Format("mvx: %d mvy: %d", mvx,mvy);
AfxMessageBox(outshow);
}
//检测运动矢量是否指向图像内部
if (!mv_outside_frame)
{
bsize = k ? 8 : 16;
offset = k ? (((k-1)&1)<<3) : 0;
//仅检测整象素(mvx/2)的MV
if((xpos<<4) + (mvx/2) + offset < 0 ||
(xpos<<4) + (mvx/2) + offset > (mb_width<<4) - bsize)
{
if (!quiet)
AfxMessageBox("mvx out of range: searching for sync!");
fault = 1;
}
offset = k ? (((k-1)&2)<<2) : 0;
if((ypos<<4) + (mvy/2) + offset < 0 ||
(ypos<<4) + (mvy/2) + offset > (mb_height<<4) - bsize)
{
if(!quiet)
AfxMessageBox("mvy out of range: searching for sync!");
fault = 1;
}
}//end of(!mv_outside_frame)
MV[0][k][ypos+1][xpos+1] = mvx;
MV[1][k][ypos+1][xpos+1] = mvy;
}//end of ( normal MV Decode)
// PB frame delta vectors
if (pb_frame)
{
if (MODB == PBMODE_MVDB || MODB == PBMODE_CBPB_MVDB)
{
if (syntax_arith_coding)
{
mvdbx_index = m_sacode.decode_a_symbol(cumf_MVD);
mvdbx = mvdtab[mvdbx_index];
mvdby_index = m_sacode.decode_a_symbol(cumf_MVD);
mvdby = mvdtab[mvdby_index];
}
else//Huff_Decode
{
mvdbx = m_getvlc.getTMNMV();
mvdby = m_getvlc.getTMNMV();
}
mvdbx = motion_decode(mvdbx, 0);
mvdby = motion_decode(mvdby, 0);
if (trace)
{
outshow.Format("MVDB x: %d MVDB y: %d ", mvdbx, mvdby);
AfxMessageBox(outshow);
}
}
else
{
mvdbx = 0;
mvdby = 0;
}
}//end of(pb_frame)
}//end of(MV Decode)
if(fault)
goto resync;
}
else //COD=1 没有块头信息 进行下一宏块的编码
{ // COD == 1 -->跳空 MB
if(MBA>=MBAmax)
return; // all macroblocks decoded
if (!syntax_arith_coding)
if (pict_type == PCT_INTER)
m_getbits.flushbits(1);
Mode = MODE_INTER;
//Reset CBP
CBP = CBPB = 0;
//Reset motion vectors
MV[0][0][ypos+1][xpos+1] = 0;
MV[1][0][ypos+1][xpos+1] = 0;
mvdbx = 0;
mvdby = 0;
}
// Store Mode
modemap[ypos+1][xpos+1] = Mode;
if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
if (!pb_frame)
MV[0][0][ypos+1][xpos+1]=MV[1][0][ypos+1][xpos+1] = 0;
/*************************************************************/
//3.解码前一宏块的块数据信息(重建预测块,IDCT Pre+Idct)
/************************************************************/
reconstruct_mb:
// 前一宏块中的象素左上角的坐标 // one delayed because of OBMC
if (xpos > 0)
{
bx = 16*(xpos-1);
by = 16*ypos;
}
else
{
bx = coded_picture_width-16;
by = 16*(ypos-1);
}
if (MBA > 0)
{
Mode = modemap[by/16+1][bx/16+1];
// 前向运动补偿 for B-frame
if (pb_frame)
m_recon.reconstruct(bx,by,0,pmvdbx,pmvdby);//P=0 B模式
// 运动补偿 for P-frame
if (Mode == MODE_INTER || Mode == MODE_INTER_Q || Mode == MODE_INTER4V)
m_recon.reconstruct(bx,by,1,0,0);//P=1 预测模式
//copy or add block data into P-picture
for (comp=0; compblock[comp]);//ld->block中存放IDCT数据
addblock(comp,bx,by,0);//将ld->block中的数据放入图像中
}
else if( (pCBP & (1<<(blk_cnt-1-comp))) )
{
//No need to to do this for blocks with no coeffs
m_idct.idct(ld->block[comp]);
addblock(comp,bx,by,1);//将ld->block中的数据放入图像中
}
}//解码宏块(normal)
if (pb_frame)
{
// add block data into B-picture
for (comp = 6; compblock[comp]);
addblock(comp,bx,by,1);
}
}
}//end of(pb_frame)
} // end if (MBA > 0)
/***************************************************************/
//4.根据(COD,Mode,CBP,)从缓存中得到比特书并放入ld->block中
/***************************************************************/
if (!COD)
{
Mode = modemap[ypos+1][xpos+1];
// decode blocks
for (comp=0; compblock中的数据首先清零
if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
{ // Intra
bp = ld->block[comp];//传递地址 结果在ld->block中
if(syntax_arith_coding)
{
INTRADC_index = m_sacode.decode_a_symbol(cumf_INTRADC);
bp[0] = intradctab[INTRADC_index];
if (trace)
{
outshow.Format("INTRADC Index: %d INTRADC: %d \n", INTRADC_index, bp[0]);
AfxMessageBox(outshow);
}
}
else
bp[0] = m_getbits.getbits(8);//直流分量
if (trace)
{
outshow.Format("DC[%d]is: %d",comp,(int)bp[0]);
AfxMessageBox(outshow);
}
if (bp[0] == 128)
if(!quiet)
AfxMessageBox("Illegal DC-coeff: 1000000!");
if (bp[0] == 255)//标准中所定
bp[0] = 128;
bp[0] *= 8; // Iquant
//解码交流分量
if( (CBP & (1<<(blk_cnt-1-comp))) )
{ //从比特流中得到数据放入ld->block[]中
if(!syntax_arith_coding)
m_getblk.getblock(comp,0);
else
m_getblk.get_sac_block(comp,0);
}
}//end of (Intra)
else
{ // Inter 没有直流系数 直接解码交流系数
if ( (CBP & (1<<(blk_cnt-1-comp))) )
{ //从比特流中得到数据放入ld->block[]中
if(!syntax_arith_coding)
m_getblk.getblock(comp,1);
else
m_getblk.get_sac_block(comp,1);
}
}//end block decode
if (fault)
goto resync;
}
// Decode B blocks
if (pb_frame)
{
for (comp=6; comp= MBAmax && !last_done)
{
COD = 1;
xpos = 0;
ypos++;
last_done = 1;
goto reconstruct_mb;
}
}//end of(for)
}
void CGetpic::clearblock(int comp)
{
int *bp;
int i;
bp = (int *)ld->block[comp];
for (i=0; i<8; i++)
{
bp[0] = bp[1] = bp[2] = bp[3] = 0;
bp += 4;
}
}
int CGetpic::motion_decode(int vec, int pmv)
{
if (vec > 31)
vec -= 64;
vec += pmv;
if (!long_vectors)
{
if (vec > 31)
vec -= 64;
if (vec < -32)
vec += 64;
}
else
{
if (pmv < -31 && vec < -63)
vec += 64;
if (pmv > 32 && vec > 63)
vec -= 64;
}
return vec;
}
int CGetpic::find_pmv(int x, int y, int block, int comp)
{
int p1,p2,p3;
int xin1,xin2,xin3;
int yin1,yin2,yin3;
int vec1,vec2,vec3;
int l8,o8,or8;
x++;y++;
l8 = (modemap[y][x-1] == MODE_INTER4V ? 1 : 0);
o8 = (modemap[y-1][x] == MODE_INTER4V ? 1 : 0);
or8 = (modemap[y-1][x+1] == MODE_INTER4V ? 1 : 0);
switch (block)
{
case 0:
vec1 = (l8 ? 2 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 1:
vec1 = (l8 ? 2 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 2:
vec1 = 1 ; yin1 = y ; xin1 = x;
vec2 = (o8 ? 4 : 0) ; yin2 = y-1; xin2 = x;
vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;
break;
case 3:
vec1 = (l8 ? 4 : 0) ; yin1 = y ; xin1 = x-1;
vec2 = 1 ; yin2 = y ; xin2 = x;
vec3 = 2 ; yin3 = y ; xin3 = x;
break;
case 4:
vec1 = 3 ; yin1 = y ; xin1 = x;
vec2 = 1 ; yin2 = y ; xin2 = x;
vec3 = 2 ; yin3 = y ; xin3 = x;
break;
default:
fprintf(stderr,"Illegal block number in find_pmv (getpic.cpp)\n");
exit(1);
break;
}
p1 = MV[comp][vec1][yin1][xin1];
p2 = MV[comp][vec2][yin2][xin2];
p3 = MV[comp][vec3][yin3][xin3];
if (newgob && (block == 0 || block == 1 || block == 2))
p2 = NO_VEC;
if (p2 == NO_VEC)
p2 = p3 = p1;
return p1+p2+p3 - mmax(p1,mmax(p2,p3)) - mmin(p1,mmin(p2,p3));
}
void CGetpic::addblock(int comp, int bx, int by, int addflag)
{
int cc,i,j, iincr, P = 1;
unsigned char *rfp;
short *bp;
bp = ld->block[comp];
if (comp >= 6)
{
// This is a component for B-frame forward prediction
P = 0;
addflag = 1;
comp -= 6;
}
cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */
if (cc==0) // luminance
{
// frame DCT coding
if (P)
rfp = newframe[0]
+ coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
else //P=0 B 帧
rfp = bframe[0]
+ coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
iincr = coded_picture_width;
}
else // chrominance
{
// scale coordinates
bx >>= 1;
by >>= 1;
//frame DCT coding
if (P)
rfp = newframe[cc] + chrom_width*by + bx;
else
rfp = bframe[cc] + chrom_width*by + bx;
iincr = chrom_width;
}
if (addflag) //帧间编码要加上预测
{
for (i=0; i<8; i++)
{
for(j=0;j<8;j++)
rfp[j]=clp[bp[j]+rfp[j]];
bp += 8;
rfp+= iincr;
}
}
else//帧内编码无须加
{
for (i=0; i<8; i++)
{
for(j=0;j<8;j++)
rfp[j]=clp[bp[j]];
bp += 8;
rfp += iincr;
}
}//end of (addflag)
}
void CGetpic::reconblock_b(int comp, int bx, int by, int mode, int bdx, int bdy)
{
int cc,i,j,k, ii;
unsigned char *bfr, *ffr;
int BMVx, BMVy;
int xa,xb,ya,yb,x,y,xvec,yvec,mvx,mvy;
int xint,xhalf,yint,yhalf,pel;
x = bx/16+1;y=by/16+1;
if (mode == MODE_INTER4V)
{
if (comp < 4)
{
/* luma */
mvx = MV[0][comp+1][y][x];
mvy = MV[1][comp+1][y][x];
BMVx = (bdx == 0 ? (trb-trd)* mvx/trd : trb * mvx/trd + bdx - mvx);
BMVy = (bdy == 0 ? (trb-trd)* mvy/trd : trb * mvy/trd + bdy - mvy);
}
else
{
/* chroma */
xvec = yvec = 0;
for (k = 1; k <= 4; k++)
{
mvx = MV[0][k][y][x];
mvy = MV[1][k][y][x];
xvec += (bdx == 0 ? (trb-trd)* mvx/trd : trb * mvx/trd + bdx - mvx);
yvec += (bdy == 0 ? (trb-trd)* mvy/trd : trb * mvy/trd + bdy - mvy);
}
/* chroma rounding (table 16/H.263) */
BMVx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
BMVy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
}
}
else {
if (comp < 4)
{
/* luma */
mvx = MV[0][0][y][x];
mvy = MV[1][0][y][x];
BMVx = (bdx == 0 ? (trb-trd)* mvx/trd : trb * mvx/trd + bdx - mvx);
BMVy = (bdy == 0 ? (trb-trd)* mvy/trd : trb * mvy/trd + bdy - mvy);
}
else
{
/* chroma */
mvx = MV[0][0][y][x];
mvy = MV[1][0][y][x];
xvec = (bdx == 0 ? (trb-trd)* mvx/trd : trb * mvx/trd + bdx - mvx);
yvec = (bdy == 0 ? (trb-trd)* mvy/trd : trb * mvy/trd + bdy - mvy);
xvec *= 4;
yvec *= 4;
/* chroma rounding (table 16/H.263) */
BMVx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
BMVy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
}
}
cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */
if (cc==0)
{
/* luminance */
find_bidir_limits(BMVx,&xa,&xb,comp&1);
find_bidir_limits(BMVy,&ya,&yb,(comp&2)>>1);
bfr = bframe[0] +
coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
ffr = newframe[0] +
coded_picture_width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
ii = coded_picture_width;
}
else
{
/* chrominance */
/* scale coordinates and vectors*/
bx >>= 1;
by >>= 1;
find_bidir_chroma_limits(BMVx,&xa,&xb);
find_bidir_chroma_limits(BMVy,&ya,&yb);
bfr = bframe[cc] + chrom_width*(by+((comp&2)<<2)) + bx + (comp&8);
ffr = newframe[cc] + chrom_width*(by+((comp&2)<<2)) + bx + (comp&8);
ii = chrom_width;
}
xint = BMVx>>1;
xhalf = BMVx - 2*xint;
yint = BMVy>>1;
yhalf = BMVy - 2*yint;
ffr += xint + (yint+ya)*ii;
bfr += ya*ii;
if (!xhalf && !yhalf)
{
for (j = ya; j < yb; j++)
{
for (i = xa; i < xb; i++)
{
pel = ffr[i];
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
else if (xhalf && !yhalf)
{
for (j = ya; j < yb; j++)
{
for (i = xa; i < xb; i++)
{
pel = (ffr[i]+ffr[i+1]+1)>>1;
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
else if (!xhalf && yhalf)
{
for (j = ya; j < yb; j++)
{
for (i = xa; i < xb; i++)
{
pel = (ffr[i]+ffr[ii+i]+1)>>1;
bfr[i] = ((unsigned int)(pel + bfr[i]))>>1;
}
bfr += ii;
ffr += ii;
}
}
else
{ /* if (xhalf && yhalf) */
for (j = ya; j < yb; j++)
{
for (i = xa; i < xb; i++)
{
pel = ((unsigned int)(ffr[i]+ffr[i+1]+ffr[ii+i]+ffr[ii+i+1]+2))>>2;
bfr[i] = (pel + bfr[i])>>1;
}
bfr += ii;
ffr += ii;
}
}
return;
}
void CGetpic::find_bidir_limits(int vec, int *start, int *stop, int nhv)
{
/* limits taken from C loop in section G5 in H.263 */
*start = mmax(0,(-vec+1)/2 - nhv*8);
*stop = mmin(7,15-(vec+1)/2 - nhv*8);
(*stop)++; /* I use < and not <= in the loop */
}
void CGetpic::find_bidir_chroma_limits(int vec, int *start, int *stop)
{
/* limits taken from C loop in section G5 in H.263 */
*start = mmax(0,(-vec+1)/2);
*stop = mmin(7,7-(vec+1)/2);
(*stop)++; /* I use < and not <= in the loop */
return;
}
void CGetpic::make_edge_image(unsigned char *src, unsigned char *dst, int width, int height, int edge)
{
int i,j;
unsigned char *p1,*p2,*p3,*p4;
unsigned char *o1,*o2,*o3,*o4;
/* center image */
p1 = dst;
o1 = src;
for (j = 0; j < height;j++)
{
for (i = 0; i < width; i++)
{
*(p1 + i) = *(o1 + i);
}
p1 += width + (edge<<1);
o1 += width;
}
/* left and right edges */
p1 = dst-1;
o1 = src;
for (j = 0; j < height;j++)
{
for (i = 0; i < edge; i++)
{
*(p1 - i) = *o1;
*(p1 + width + i + 1) = *(o1 + width - 1);
}
p1 += width + (edge<<1);
o1 += width;
}
/* top and bottom edges */
p1 = dst;
p2 = dst + (width + (edge<<1))*(height-1);
o1 = src;
o2 = src + width*(height-1);
for (j = 0; j < edge;j++)
{
p1 = p1 - (width + (edge<<1));
p2 = p2 + (width + (edge<<1));
for (i = 0; i < width; i++)
{
*(p1 + i) = *(o1 + i);
*(p2 + i) = *(o2 + i);
}
}
/* corners */
p1 = dst - (width+(edge<<1)) - 1;
p2 = p1 + width + 1;
p3 = dst + (width+(edge<<1))*(height)-1;
p4 = p3 + width + 1;
o1 = src;
o2 = o1 + width - 1;
o3 = src + width*(height-1);
o4 = o3 + width - 1;
for (j = 0; j < edge; j++) {
for (i = 0; i < edge; i++) {
*(p1 - i) = *o1;
*(p2 + i) = *o2;
*(p3 - i) = *o3;
*(p4 + i) = *o4;
}
p1 = p1 - (width + (edge<<1));
p2 = p2 - (width + (edge<<1));
p3 = p3 + width + (edge<<1);
p4 = p4 + width + (edge<<1);
}
}
// only used for displayed interpolated frames, not reconstructed ones
void CGetpic::interpolate_image(unsigned char *in, unsigned char *out, int width, int height)
{
int x,xx,y,w2;
unsigned char *pp,*ii;
w2 = 2*width;
// Horizontally
pp = out;
ii = in;
for (y = 0; y < height-1; y++)
{
for (x = 0,xx=0; x < width-1; x++,xx+=2)
{
*(pp + xx) = *(ii + x);
*(pp + xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1)))>>1;
*(pp + w2 + xx) = ((unsigned int)(*(ii + x) + *(ii + x + width)))>>1;
*(pp + w2 + xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) +
*(ii + x + width) + *(ii + x + width + 1)))>>2;
}
*(pp + w2 - 2) = *(ii + width - 1);
*(pp + w2 - 1) = *(ii + width - 1);
*(pp + w2 + w2 - 2) = *(ii + width + width - 1);
*(pp + w2 + w2 - 1) = *(ii + width + width - 1);
pp += w2<<1;
ii += width;
}
// last lines
for (x = 0,xx=0; x < width-1; x++,xx+=2)
{
*(pp+ xx) = *(ii + x);
*(pp+ xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + 1))>>1;
*(pp+ w2+ xx) = *(ii + x);
*(pp+ w2+ xx+1) = ((unsigned int)(*(ii + x) + *(ii + x + 1) + 1))>>1;
}
// bottom right corner pels
*(pp + (width<<1) - 2) = *(ii + width -1);
*(pp + (width<<1) - 1) = *(ii + width -1);
*(pp + (width<<2) - 2) = *(ii + width -1);
*(pp + (width<<2) - 1) = *(ii + width -1);
return;
}