📄 mpeg2dec.cpp
字号:
SEQEND=false;
base.Infile=pMPG2->ld->Infile;
GlobalUnlock(hMPG2);
}
void GetParam(environment_data *pMPG2,LPBYTE lpBuf)
{
short N=0;
short M=0;
BOOL FirstP=false;
BOOL FirstFrame=false;
if(pMPG2->mode==0)
{
SEQEND=false;
//记录M,N
lseek(ld->Infile, 0l, 0);
if(ld->Infile!=0)
{
lseek(ld->Infile, 0l, 0);
}
Initialize_Buffer();
while(Headers())
{
//得到开始时间
if(picture_coding_type==I_TYPE&&!FirstFrame)
{
pMPG2->tframe=frame;
pMPG2->tsec=sec;
pMPG2->tminute=minute;
pMPG2->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_Sequence1();
pMPG2->cur_position=0l;
pMPG2->M=M;
pMPG2->N=N;
pMPG2->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;
}
if(frame_rate==0)
frame_rate=25;
MaxFrame=bit_rate/(frame_rate*8); //估计帧大小
FileSize=_filelengthi64(ld->Infile); //得到文件长度
if(OK_ID)
initscale(); //初始化缩放
}
else
{
SEQEND=false;
base.lpData=lpBuf;
base.size=80000;
base.length=0;
//记录M,N
Initialize_Buffer();
Headers();
tframe=frame;
tsec=sec;
tminute=minute;
thour=hour;
pMPG2->tframe=frame;
pMPG2->tsec=sec;
pMPG2->tminute=minute;
pMPG2->thour=hour;
SEQEND=false;
Initialize_Sequence1();
pMPG2->cur_position=0l;
//确定缩放比例系数
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;
}
if(OK_ID)
initscale();
}
}
HANDLE okMPG2BeginDecode(LPSTR infile)
{
HANDLE hMPG2;
environment_data *pMPG2;
hMPG2=GlobalAlloc(GHND,sizeof(environment_data));
if(!hMPG2)
return NULL;
// Error("alloc hDecode mem fail");
pMPG2=(environment_data *)GlobalLock(hMPG2);
pMPG2->hFilesize=sizeof(environment_data);
// pMPG2->ld=(layer_data*)malloc(sizeof(layer_data));
pMPG2->ld=(layer_data*)GlobalAlloc(GPTR,sizeof(layer_data));
memset(pMPG2->ld,0,sizeof(layer_data));
ld=&base;
memset(ld,0,sizeof(layer_data));
// ::MessageBox(NULL,infile,"okMPG2BeginDecode",MB_OK);
if(infile)
{
// ::MessageBox(NULL,infile,"okMPG2BeginDecode",MB_OK);
pMPG2->mode=0;
int temp=open(infile,O_RDONLY|O_BINARY);
pMPG2->ld->Infile=temp;
if(temp==-1)
{
return NULL;
}
pMPG2->ld->mode=0;
pMPG2->frameno=1;
}
else
{
// ::MessageBox(NULL,"pMPG2->mode=1","okMPG2BeginDecode",MB_OK);
pMPG2->mode=1;
pMPG2->ld->mode=1;
pMPG2->frameno=1;
}
init_dither_tab();
Initialize_Decoder();
GlobalUnlock(hMPG2);
return hMPG2;
}
typedef struct //数据头结构
{
// 公用部分
long headsize; //数据头大小
long totalframe; //总帧数 (out)
long horizontal_size; //宽度,缺省768 (in,out)
long vertical_size; //高度,缺省576 (in,out)
double frame_rate; //帧速率,缺省25.0 (in,out)
//用于MJPG的参数
long quality; /*jpeg质量因子,缺省75,(in) 若大于此值会增加编码时间,
在某些情况下无法达到实时采集*/
long color;
//用于MPEG4编码器,建议以下采用缺省值
double bit_rate; // 位速率,缺省值4000000(in)。码位率过低降低图像质量。
long Encode_Mode; /*编码模式 ,缺省值0(in),范围(0-1)整数。=0表示双通道;
=1表示固定码率,固定码率值为bit_rate*/
long Interval; /*关键帧间隔,缺省值100(in),范围(1--300)整数.
此值过高会降低反向播放的速度。过低会降低压缩比。*/
long BNum; /*B帧模式,缺省值0(in),范围(0-2)整数. =0时可以保证实时采集;
=1是与divx5.0兼容,=2可以大大提高压缩比,
但是会增加编码时间,在某些情况下无法达到实时采集。*/
long Q; /*mpeg4质量因子,缺省值0(in). 范围(0---6)之间整数,
值越高图像质量越好,但会增加编码时间,无法进行实时采集。*/
long reserved1; //保留
long reserved2; //保留
long reserved3; //保留
long reserved4; //保留
}video_param;
BOOL okMPG2GetHeader(HANDLE hMPG2, LPBYTE lpData,LPARAM head1)
{
long total;
char temp[16];
// ::MessageBox(NULL,NULL,"okMPG2GetHeader",MB_OK);
video_param *head;
head=(video_param*)head1;
if(!head || !hMPG2)
return false;
total=head->totalframe;
environment_data *pMPG2;
// memset(head,1,sizeof(video_param));
pMPG2=(environment_data *)GlobalLock(hMPG2);
if(!pMPG2)
{
// ::MessageBox(NULL,"pMPG2=NULL","okMPG2GetHeader",MB_OK);
return false;
}
memcpy(&base,pMPG2->ld,sizeof(layer_data));
hour=pMPG2->hour;
minute=pMPG2->minute;
sec=pMPG2->sec;
frame=pMPG2->frame;
thour=pMPG2->thour;
tminute=pMPG2->tminute;
tsec=pMPG2->tsec;
tframe=pMPG2->tframe;
if(check_stream(pMPG2,lpData)==0)
return FALSE;
GetParam(pMPG2,lpData);
if(pMPG2->mode==0)
{
GetTotalFrame(hMPG2,&total);
char str[100];
sprintf( str, "total=%d,SEQEND=%d", total,SEQEND);
// ::MessageBox(NULL,str,"okMPG2GetHeader",MB_OK);
}
if(frame_rate==0)
frame_rate=25;
TotalFrame=total;
head->headsize=sizeof(header_data);
head->totalframe=total;
head->bit_rate=bit_rate;
head->frame_rate=frame_rate;
head->color=24;
pMPG2->width=horizontal_size;
pMPG2->height=vertical_size;
pMPG2->OK_ID=OK_ID;
if(fabs(factor-1.000)>0.001)
head->horizontal_size=WIDTHBYTES((int)((double)horizontal_size*factor))*8;
else
head->horizontal_size=horizontal_size;
head->vertical_size=vertical_size;
pMPG2->factor=factor;
pMPG2->mb_height=mb_height;
pMPG2->mb_width=mb_width;
pMPG2->Chroma_Width =Chroma_Width ;
pMPG2->Chroma_Height=Chroma_Height ;
pMPG2->block_count=block_count;
pMPG2->FileSize=FileSize;
pMPG2->frame_rate=frame_rate;
for (int cc=0; cc<3; cc++)
{
long size=0;
if (cc==0)
size = Coded_Picture_Width*Coded_Picture_Height;
else
size = Chroma_Width*Chroma_Height;
if(!pMPG2->backward_reference_frame[cc])
pMPG2->backward_reference_frame[cc] = (unsigned char *)malloc(size);
if(!pMPG2->forward_reference_frame[cc])
pMPG2->forward_reference_frame[cc] = (unsigned char *)malloc(size);
if(!pMPG2->auxframe[cc])
pMPG2->auxframe[cc] = (unsigned char *)malloc(size);
}
if(pMPG2->mode==0)
pMPG2->total=total;
else
pMPG2->total=100;
memcpy(pMPG2->ld,&base,sizeof(layer_data));
GlobalUnlock(hMPG2);
return true;
}
void okMPG2EndDecode(HANDLE hMPG2)
{
environment_data *pMPG2;
pMPG2=(environment_data *)GlobalLock(hMPG2);
memcpy(&base,pMPG2->ld,sizeof(layer_data));
for(int i=0;i<3;i++)
{
backward_reference_frame[i]=pMPG2->backward_reference_frame[i];
forward_reference_frame[i]=pMPG2->forward_reference_frame[i];
auxframe[i]=pMPG2->auxframe[i];
}
AUDIO=false;
SEQEND=false;
ClearGlobal();
Initialize_Buffer();
// ::MessageBox(NULL,NULL,"okMPG2EndDecode",MB_OK);
Deinitialize_Sequence();
if(pMPG2->mode==0)
{
char str[100];
sprintf( str, "Infile=%d", pMPG2->ld->Infile,SEQEND);
lseek(pMPG2->ld->Infile, 0l, 0);
// ::MessageBox(NULL,str,"okMPG2EndDecode",MB_OK);
_close(pMPG2->ld->Infile);
}
//free(pMPG2->ld);
GlobalFree(pMPG2->ld);
GlobalUnlock(hMPG2);
GlobalFree(hMPG2);
}
long okMPG2ReadFrame(HANDLE hMPG2,LPBYTE lpBuf, long lParam, LPBYTE dst,long stride)
{
//分配存储空间
long offset=0; //存储偏移量
unsigned char *Framedst1; //解码缓存指针
environment_data *pMPG2; //文件指针
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; //图像组位置标记
long frameno;
long framenum=1;
long Mode=2;
long TotalFrame;
long remain=0;
long tlframe=0;
long b,e;
// ::MessageBox(NULL,NULL,"okMPG2ReadFrame",MB_OK);
pMPG2=(environment_data *)GlobalLock(hMPG2); //分配环境变量
if(pMPG2->mode==0)
frameno=lParam+1;
else
frameno=pMPG2->frameno;
for(int i=0;i<3;i++)
{
backward_reference_frame[i]=pMPG2->backward_reference_frame[i];
forward_reference_frame[i]=pMPG2->forward_reference_frame[i];
auxframe[i]=pMPG2->auxframe[i];
}
b=tell(pMPG2->ld->Infile);
horizontal_size=pMPG2->width;
vertical_size=pMPG2->height;
memcpy(&base,pMPG2->ld,sizeof(layer_data));
mb_height=pMPG2->mb_height;
mb_width=pMPG2->mb_width;
System_Stream_Flag=pMPG2->System_Stream_Flag;
factor=pMPG2->factor;
TotalFrame=pMPG2->total;
Coded_Picture_Height=pMPG2->height;
Coded_Picture_Width=pMPG2->width;
Chroma_Width = pMPG2->Chroma_Width;
Chroma_Height = pMPG2->Chroma_Height;
block_count=pMPG2->block_count;
OK_ID=pMPG2->OK_ID;
FileSize=pMPG2->FileSize;
TotalFrame=pMPG2->total;
frame_rate=pMPG2->frame_rate;
//分配存储空间
Framedst1=(unsigned char*)malloc(Coded_Picture_Height*Coded_Picture_Width*3);
if(!Framedst1)
Error("alloc frame mem fail");
//初始化
N=pMPG2->N;
M=pMPG2->M;
decode_Framenum=0;
cal=N+M+1;
interval=4*(N+M+1);
AUDIO=false;
SEQEND=false;
FirstI=false;
SKIP=true;
if(frameno==pMPG2->cur_bitno+1)
{
if(pMPG2->mode==0)
{
//连续解码
SKIP=false;
//初始化播放时间
base.length=0;
//指向当前帧位置
_lseeki64(ld->Infile,pMPG2->cur_position,SEEK_SET);
}
else
{
//连续解码
if(frameno==1)
base.lpData=lpBuf;
base.length=0;
base.size=lParam;
SKIP=false;
//初始化播放时间
}
hour=pMPG2->hour;
minute=pMPG2->minute;
sec=pMPG2->sec;
lframe=pMPG2->lframe;
frame=pMPG2->frame;
thour=pMPG2->thour;
tminute=pMPG2->tminute;
tsec=pMPG2->tsec;
tlframe=pMPG2->tlframe;
tframe=pMPG2->tframe;
}
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);
}
thour=pMPG2->thour;
tminute=pMPG2->tminute;
tsec=pMPG2->tsec;
tlframe=pMPG2->tlframe;
tframe=pMPG2->tframe;
//跳跃解码
//计算粗略文件位置
filecur=FileSize*(_int64)(frameno-interval)/(_int64)(TotalFrame);
filecur=filecur/2048*2048;
if(filecur>=0)
_lseeki64(ld->Infile,filecur,SEEK_SET);
else
lseek(ld->Infile,0l,SEEK_SET);
Initialize_Buffer();
}
//开始解码
SEQEND=false; //文件末尾标记
while(1)
{
if(!Headers() && SEQEND)
{
pMPG2->hour=hour;
pMPG2->minute=minute;
pMPG2->sec=sec;
pMPG2->frame=frame;
pMPG2->lframe=lframe;
pMPG2->cur_bitno=frameno;
pMPG2->cur_position=_telli64(ld->Infile);
break;
}
if(picture_coding_type==I_TYPE)
{
//寻找图像组首位置
FirstI=true;
lframe=0; //组内序号归零
}
else
{
//若不是图像组首且为非连续解码,则继续寻找。
if((frameno<2 && !FirstI) || SKIP )
{
FirstI=TRUE; //组内序号加1
continue;
}
}
if(SEQEND)
{
::MessageBox(NULL,NULL,"SEQEND",MB_OK);
memset(Framedst1,0,Coded_Picture_Height*Coded_Picture_Width*3);
SaveFrame(Framedst1,dst,Mode,&offset,stride);
break;
}
//跳跃解码
if(SKIP)
{
if(FirstI)
{
Decode_Picture(-1, -1,Framedst1);
//若等于解码帧号转换并存储
SaveFrame(Framedst1,dst,Mode,&offset,stride);
//存储帧累加
decode_Framenum++;
pMPG2->hour=hour;
pMPG2->minute=minute;
pMPG2->sec=sec;
pMPG2->frame=frame;
pMPG2->lframe=lframe;
pMPG2->cur_bitno=frameno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -