📄 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -