📄 mpeg2dec.cpp
字号:
*total=temp;
}
lseek(pDecode->infile, 0l, 0);
if(pDecode->infile!=0)
{
lseek(pDecode->infile, 0l, 0);
}
Initialize_Buffer();
SEQEND=false;
base.Infile=pDecode->infile;
GlobalUnlock(hDecode);
}
int scale[768];
int scaleB[768];
int scaleT[1024][1024];
//初始化缩放表
void initscale()
{
long sw=horizontal_size;
long dw=WIDTHBYTES((int)((double)sw*factor))*8;
if(fabs(factor-1.0000)<0.0001)
dw=sw;
for ( int j = 0; j < dw; j++ )
{
scale[j] = j * sw / dw;
scaleB[j] = dw-j * sw % dw;
}
for ( j = -256; j < 256; j++ )
for ( int i = 0; i <dw; i++ )
{
scaleT[256+j][i]=j*i/dw;
}
}
void GetHeader1(HANDLE hDecode)
{
short N=0;
short M=0;
BOOL FirstP=false;
BOOL FirstFrame=false;
environment_data *pDecode;
pDecode=(environment_data *)GlobalLock(hDecode);
base.Infile=pDecode->infile;
SEQEND=false;
//记录M,N
lseek(pDecode->infile, 0l, 0);
if(pDecode->infile!=0)
{
lseek(pDecode->infile, 0l, 0);
}
Initialize_Buffer();
while(Headers())
{
//得到开始时间
if(picture_coding_type==I_TYPE&&!FirstFrame)
{
tframe=frame;
tsec=sec;
tminute=minute;
thour=hour;
FirstFrame=true;
}
if(picture_coding_type==P_TYPE&&N>1)
{
FirstP=true;
}
if(picture_coding_type==I_TYPE&&N>1)
{
break;
}
if(!FirstP)
M++;
N++;
}
SEQEND=false;
Initialize_Sequence();
pDecode->cur_position=0l;
pDecode->M=M;
pDecode->N=N;
pDecode->infile=base.Infile;
//确定缩放比例系数
if(OK_ID)
{
if(vertical_size==576||vertical_size==384||vertical_size==288)
factor=768.0/720.0;
else if(vertical_size==480||vertical_size==320||vertical_size==240)
factor=640.0/720.0;
else
{
factor=1.000;
}
}
else
{
factor=1.000;
}
MaxFrame=bit_rate/(frame_rate*8); //估计帧大小
FileSize=_filelengthi64(pDecode->infile); //得到文件长度
initscale(); //初始化缩放表
GlobalUnlock(hDecode);
}
int Stretch_Linear(unsigned char *src,unsigned char *dst2,long width,long height,long stride, double factor, int nPixelSize)
{
long sw = width , sh = height, dw = WIDTHBYTES((int)((double)sw*factor))*8, dh = sh;
long B;
long x;
unsigned char * pLinePrev;
unsigned char * pA, *pB;
if(fabs(factor-1.000)<0.001)
{
dw=sw;
}
long Width=dw*nPixelSize;
long sWidth=sw*nPixelSize;
long dw14=dw/4;
long dw34=dw*3/4;
long off;
if(stride<0)
off=abs(stride+Width);
else
off=stride-Width;
for (int i = 0; i <dh; i++ )
{
pLinePrev=src;
for ( int j = 0; j < dw; j++ )
{
x = scale[j]*nPixelSize;
B = scaleB[j];
pA = pLinePrev + x;
pB = pA + nPixelSize;
if (dw-B<=dw14) //目标点在原始点左1/4
{
*dst2++=*pA++;
if(nPixelSize>1)
{
*dst2++=*pA++;
*dst2++=*pA++;
}
}
else if(dw-B>=dw34) //在右3/4
{
*dst2++=*pB++;
if(nPixelSize>1)
{
*dst2++=*pB++;
*dst2++=*pB++;
}
}
else //在中间1/2
{
//线性差值
*dst2++=scaleT[(*pA-*pB)+256][B]+*pB;
if(nPixelSize>1)
{
*dst2++=scaleT[(*(pA+1)-*(pB+1))+256][B]+*(pB+1);
*dst2++=scaleT[(*(pA+2)-*(pB+2))+256][B]+*(pB+2);
}
}
}
src+=sWidth;
dst2+=off;
if(stride<0)
{
dst2+=stride;
dst2+=stride;
}
}
return 0;
}
void YUVtoRGB24(unsigned char *src,unsigned char *buf1,long width,long height,long stride)
{
short Y,U,V,B,G,R;
long Ysize=width*height;
long Usize=Ysize+Chroma_Width*Chroma_Height;
long off;
long Yi,Vi;
long woff=width/2;
long i,j;
unsigned char *dsts; //解码缓存指针
Yi=0;
Vi=0;
if(OK_ID)
{
if(!(dsts=(unsigned char*)GlobalAlloc(GMEM_FIXED,width*height*3*sizeof(unsigned char))))
Error("alloc frame mem fail");
for (j=0;j<height;j++)
{
for (i=0;i<width;i++)
{
Y=*(src+Yi);
Yi++;
U=*(src+Vi+Ysize);
V=*(src+Vi+Usize);
if(chroma_format==CHROMA420)
{
if(j%2!=0&&i==0)
{
Vi-=woff;
}
else
{
if(i%2!=0)
Vi++;
}
}
else if(chroma_format==CHROMA422)
{
if(i%2!=0)
Vi++;
}
else
{
Vi++;
}
B = Clip[(tab_76309[Y] + cbu_tab[U]) >> 16];
G = Clip[(tab_76309[Y] - cgu_tab[U] - cgv_tab[V]) >> 16];
R = Clip[(tab_76309[Y] + crv_tab[V]) >> 16];
if(j<vertical_size&&i<horizontal_size)
{
*dsts=B;
dsts++;
*dsts=G;
dsts++;
*dsts=R;
dsts++;
}
}
}
dsts-=vertical_size*horizontal_size*3;
//缩放
Stretch_Linear(dsts,buf1,horizontal_size,vertical_size,stride, factor,3);
GlobalFree(dsts);
}
else
{
long off;
int Width=3*width;
if(stride<0)
off=abs(stride+Width);
else
off=stride-Width;
dsts=buf1;
if(!dsts)
{
Error("alloc frame mem fail");
}
for (j=0;j<height;j++)
{
for (i=0;i<width;i++)
{
Y=*(src+Yi);
Yi++;
U=*(src+Vi+Ysize);
V=*(src+Vi+Usize);
if(chroma_format==CHROMA420)
{
if(j%2!=0&&i==0)
{
Vi-=woff;
}
else
{
if(i%2!=0)
Vi++;
}
}
else if(chroma_format==CHROMA422)
{
if(i%2!=0)
Vi++;
}
else
{
Vi++;
}
B = Clip[(tab_76309[Y] + cbu_tab[U]) >> 16];
G = Clip[(tab_76309[Y] - cgu_tab[U] - cgv_tab[V]) >> 16];
R = Clip[(tab_76309[Y] + crv_tab[V]) >> 16];
if(j<vertical_size&&i<horizontal_size)
{
*dsts=B;
dsts++;
*dsts=G;
dsts++;
*dsts=R;
dsts++;
}
}
dsts+=off;
if(stride<0)
{
dsts+=stride;
dsts+=stride;
}
}
}
}
void YUVtoGRAY8(unsigned char *src,unsigned char *buf1,long width,long height,long stride)
{
short Y,U,V,B,G,R;
long Width=horizontal_size*1;
long Ysize=width*height;
long Usize=Ysize+Chroma_Width*Chroma_Height;
long off;
long Yi,Vi;
long woff=width/2;
long i,j;
unsigned char *dsts; //解码缓存指针
Yi=0;
Vi=0;
if(stride<0)
off=abs(stride+Width);
else
off=stride-Width;
dsts=(unsigned char*)GlobalAlloc(GMEM_FIXED,width*height*3*sizeof(unsigned char));
if(!dsts)
{
Error("alloc frame mem fail");
}
for (j=0;j<height;j++)
{
for (i=0;i<width;i++)
{
Y=*(src+Yi);
Yi++;
B = Y;
if(j<vertical_size&&i<horizontal_size)
{
*dsts=B;
dsts++;
}
}
}
dsts-=vertical_size*horizontal_size;
Stretch_Linear(dsts,buf1,horizontal_size,vertical_size,stride, factor,1);
GlobalFree(dsts);
}
void YUVtoYUV422(unsigned char *src,unsigned char *buf1,long width,long height,long stride)
{
short Y,U,V,B,G,R;
long Width=horizontal_size*2;
long Ysize=width*height;
long Usize=Ysize+Chroma_Width*Chroma_Height;
long off;
long Yi,Vi;
long woff=width/2;
long i,j;
Yi=0;
Vi=0;
if(stride<0)
off=abs(stride+Width);
else
off=stride-Width;
for (j=0;j<height;j++)
{
for (i=0;i<width;i++)
{
Y=*(src+Yi);
Yi++;
U=*(src+Vi+Ysize);
V=*(src+Vi+Usize);
if(chroma_format==CHROMA420)
{
if(j%2!=0&&i==0)
{
Vi-=woff;
if(i%2!=0)
Vi++;
}
else
{
if(i%2!=0)
Vi++;
}
}
else if(chroma_format==CHROMA422)
{
if(i%2!=0)
Vi++;
}
else
{
Vi++;
}
if(j<vertical_size&&i<horizontal_size){
if(i%2==0)
*buf1=U;
else
*buf1=V;
buf1++;
*buf1=Y;
buf1++;}
}
buf1+=off;
if(stride<0)
{
buf1+=stride;
buf1+=stride;
}
}
}
void SaveFrame(unsigned char* Framedst1,unsigned char* dst,short Mode,long* offset,long stride)
{
switch(Mode)
{
case GRAY8:
YUVtoGRAY8(Framedst1,dst+*offset, Coded_Picture_Width,Coded_Picture_Height,stride);
(*offset)+=vertical_size*stride;
break;
case RGB24:
YUVtoRGB24(Framedst1,dst+*offset, Coded_Picture_Width,Coded_Picture_Height,stride);
(*offset)+=vertical_size*stride;
break;
case YUV422:
YUVtoYUV422(Framedst1,dst+*offset, Coded_Picture_Width,Coded_Picture_Height,stride);
(*offset)+=vertical_size*stride;
break;
case YUV420:
memcpy(dst+*offset,Framedst1,Coded_Picture_Height*abs(stride));
(*offset)+=vertical_size*stride;
break;
default:
break;
}
}
short DecodeMpeg2(HANDLE hDecode, unsigned char *dst, long framenum,long frameno, short Mode,long stride)
{
//分配存储空间
long offset=0; //存储偏移量
unsigned char *Framedst1; //解码缓存指针
environment_data *pDecode; //文件指针
short decode_Framenum; //实际解码帧数
short N,M; //N,M变量
short cal; //跳跃解码间隔
long CurFrame=0; //当前帧号
long lframe=0; //图像组内序号
BOOL SKIP; //跳跃解码标记
_int64 interval; //文件位置跨度
_int64 filecur; //粗略文件位置
BOOL BACK; //文件位置后向查找标记
BOOL FirstI; //图像组位置标记
if(frameno-1>=TotalFrame) //若帧号大于总帧数则返回0
{
memset(Framedst1,0,Coded_Picture_Height*Coded_Picture_Width*3);
SaveFrame(Framedst1,dst,Mode,&offset,stride);
return 0;
}
//分配存储空间
Framedst1=(unsigned char*)malloc(Coded_Picture_Height*Coded_Picture_Width*3);
if(!Framedst1)
Error("alloc frame mem fail");
pDecode=(environment_data *)GlobalLock(hDecode); //分配环境变量
base.Infile=pDecode->infile;
//初始化
N=pDecode->N;
M=pDecode->M;
decode_Framenum=0;
cal=N+M+1;
interval=4*(N+M+1);
AUDIO=false;
SEQEND=false;
FirstI=false;
SKIP=true;
if(frameno==pDecode->cur_bitno+1)
{
//连续解码
SKIP=false;
//初始化播放时间
hour=pDecode->hour;
minute=pDecode->minute;
sec=pDecode->sec;
lframe=pDecode->lframe;
frame=pDecode->frame;
//指向当前帧位置
_lseeki64(pDecode->infile,pDecode->cur_position,SEEK_SET);
}
else
{
for (int cc=0; cc<3; cc++)
{
long size;
if (cc==0)
size = Coded_Picture_Width*Coded_Picture_Height;
else
size = Chroma_Width*Chroma_Height;
memset(backward_reference_frame[cc],0,size);
memset(forward_reference_frame[cc],0,size);
memset(auxframe[cc],0,size);
}
//跳跃解码
//计算粗略文件位置
filecur=FileSize*(_int64)(frameno-interval)/(_int64)(TotalFrame);
filecur=filecur/2048*2048;
if(filecur>=0)
_lseeki64(pDecode->infile,filecur,SEEK_SET);
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -