您的位置:首页 > 其它

MPEG4基础知识简介以及 判断MPEG4的I, P, B帧

2013-06-28 11:44 357 查看
基础知识参看 : http://www.docin.com/p-367796495.html

当用一副图像来作为一个VO的时候,VOP就对应于具体某一帧了,因为VOP是VO特定时间点的表现

mpeg-4提出了视频对象(Video Object )的概念,将一幅图像分为几个视频对象。例如一幅图像中,人物作为一个对象,背景为另一个对象。VOP(Video Object Plant )-视频对象平面,是一个VO的时间采样。但是实际的编码器中,还是将整个图像作为一个对象处理,这样VOP就与以往帧的概念完全相同。P帧,即前向参考帧,是以当前帧之前的I、P帧为参考帧的编码图像。B帧,双向参考帧,以当前帧之前和之后的图像帧为参考帧的编码图像。而一个gov是由一个由i帧开始的,若干P、B帧组成的一个图像组,具体包含多少帧图像,由相关的编码器参数决定。


今天就把MPEG4码流的分析和它的I,P,B
Frame的判定方法在这里简要记录一下吧,供日后的翻看和大家的参考。!

 

MPEG4码流分析:

0x00,
0x00, 0x01, 0xB0作为一个VOS的开始;

0x00,
0x00, 0x01, 0xB6作为一个VOP的开始,紧跟着VOP开始的,有一个2bit 的标志,用来表示这个Frame到底是一个 I
Frame,P
Frame,B
Frame抑或是S
Frame(GMS-VOP)

标志如下:

00: I Frame

01: P Frame

10: B Frame

11: S Frame

 

但是,有关这 2bit 是在0xB6的后面字节的高位还是低位,却没有很明确的描述。

于是又回头开始针对某个MPEG4编码好的文件开始分析,结果终于发现,判定方法如下:

1.可以写一个判定VOP,或者VOS开头的函数:

static unsigned char *Find_VOP_Start(unsigned
char *addrp, unsigned int FindSizes)

{

       while(pos
< FindSizes)

       {

              if(addrp[pos]
== 0x00)

                     if(addrp[pos
+ 1] == 0x00)  

                            if(addrp[pos
+ 2] == 0x01)  

                                   if(addrp[pos
+ 3] == 0xB0)

                                          break;        //判断是否是VOS头

                                  

                                   if(addrp[pos]
== 0x00)

                                          if(addrp[pos
+ 1] == 0x00)  

                                                 if(addrp[pos
+ 2] == 0x01)  

                                                        if(addrp[pos
+ 3] == 0xB6)

                                                               break;        //判断是否是VOP头

             

pos++;

       }

 

       if(pos<
FindSizes - 4)

       {    

              return
addrp+pos+4;

       }

       else  

              return
NULL;

}

 

2. 读一个MPEG4码流文件,然后利用刚才写的函数搜索StartCode:

       size_t
nRead = fread(lpSrc, 1, lSize, fp);

       fseek(fp,
0, SEEK_SET);

       while
(!feof(fp))

       {

              unsigned
char *p=Find_VOP_Start(lpSrc,lSize);

              if
(pos)    //pos为文件当前指针

              {

                     length=pos-poslast+header;   //每帧长度为两个StartCode之间的字节数

                     if
(length  

{

//长度小于一定值,则不够一帧大小,表示在I
frame前面的VOS,VO,VOL头

                            header=length;

                     }

                     else

                     {

                            header=0;

                            if
(0==(nInput=fread(buffer,1,length,fp))) break; //读取一帧大小数据,

                            //调用解码器接口,进行解码测试操作;……

                     }

              }

              if
(p==NULL) break;

              //判定VOS是哪种profile

              if
(*(p-1)==0xB0)

              {

                     if
(*p==0xF5)  printf("VOS Header start,Advanced Simple Profile level 5!/n");

                     else
if (*p==0x1) printf("VOS Header start,Simple Profile level 1!/n");

                     else
if (*p==0x2)  printf("VOS Header start,Simple Profile level 2/n!");

            ……

                     else  printf("VOS
Header Start,Other profile@level/n!");

              }

              if
(*(p-1)==0xB6)

              {

                     //判定是I,P,B
,S  Frame

                     if
((*p & 0xC0)==0x00)       printf("VOP-I frame # %d, ", frames++);

                     else
if ((*p & 0xC0)==0x40) printf("VOP-P frame # %d, ", frames++);

                     else
if ((*p & 0xC0)==0x80) printf("VOP-B frame # %d, ", frames++);

                     else
if ((*p & 0xC0)==0xC0) printf("VOP-S frame # %d, ", frames++);

                     else   printf("VOP-unknown
type frame # %d, ",frames++);

              }

              //继续查找下一个VOS/VOP的StartCode

              poslast=pos;

              pos=pos+4;   

       }

今天就把MPEG4码流的分析和它的I,P,B
Frame的判定方法在这里简要记录一下吧,供日后的翻看和大家的参考。!

 

MPEG4码流分析:

0x00,
0x00, 0x01, 0xB0作为一个VOS的开始;

0x00,
0x00, 0x01, 0xB6作为一个VOP的开始,紧跟着VOP开始的,有一个2bit 的标志,用来表示这个Frame到底是一个 I
Frame,P
Frame,B
Frame抑或是S
Frame(GMS-VOP)

标志如下:

00: I Frame

01: P Frame

10: B Frame

11: S Frame

 

但是,有关这 2bit 是在0xB6的后面字节的高位还是低位,却没有很明确的描述。

于是又回头开始针对某个MPEG4编码好的文件开始分析,结果终于发现,判定方法如下:

1.可以写一个判定VOP,或者VOS开头的函数:

static unsigned char *Find_VOP_Start(unsigned
char *addrp, unsigned int FindSizes)

{

       while(pos
< FindSizes)

       {

              if(addrp[pos]
== 0x00)

                     if(addrp[pos
+ 1] == 0x00)  

                            if(addrp[pos
+ 2] == 0x01)  

                                   if(addrp[pos
+ 3] == 0xB0)

                                          break;        //判断是否是VOS头

                                  

                                   if(addrp[pos]
== 0x00)

                                          if(addrp[pos
+ 1] == 0x00)  

                                                 if(addrp[pos
+ 2] == 0x01)  

                                                        if(addrp[pos
+ 3] == 0xB6)

                                                               break;        //判断是否是VOP头

             

pos++;

       }

 

       if(pos<
FindSizes - 4)

       {    

              return
addrp+pos+4;

       }

       else  

              return
NULL;

}

 

2. 读一个MPEG4码流文件,然后利用刚才写的函数搜索StartCode:

       size_t
nRead = fread(lpSrc, 1, lSize, fp);

       fseek(fp,
0, SEEK_SET);

       while
(!feof(fp))

       {

              unsigned
char *p=Find_VOP_Start(lpSrc,lSize);

              if
(pos)    //pos为文件当前指针

              {

                     length=pos-poslast+header;   //每帧长度为两个StartCode之间的字节数

                     if
(length  

{

//长度小于一定值,则不够一帧大小,表示在I
frame前面的VOS,VO,VOL头

                            header=length;

                     }

                     else

                     {

                            header=0;

                            if
(0==(nInput=fread(buffer,1,length,fp))) break; //读取一帧大小数据,

                            //调用解码器接口,进行解码测试操作;……

                     }

              }

              if
(p==NULL) break;

              //判定VOS是哪种profile

              if
(*(p-1)==0xB0)

              {

                     if
(*p==0xF5)  printf("VOS Header start,Advanced Simple Profile level 5!/n");

                     else
if (*p==0x1) printf("VOS Header start,Simple Profile level 1!/n");

                     else
if (*p==0x2)  printf("VOS Header start,Simple Profile level 2/n!");

            ……

                     else  printf("VOS
Header Start,Other profile@level/n!");

              }

              if
(*(p-1)==0xB6)

              {

                     //判定是I,P,B
,S  Frame

                     if
((*p & 0xC0)==0x00)       printf("VOP-I frame # %d, ", frames++);

                     else
if ((*p & 0xC0)==0x40) printf("VOP-P frame # %d, ", frames++);

                     else
if ((*p & 0xC0)==0x80) printf("VOP-B frame # %d, ", frames++);

                     else
if ((*p & 0xC0)==0xC0) printf("VOP-S frame # %d, ", frames++);

                     else   printf("VOP-unknown
type frame # %d, ",frames++);

              }

              //继续查找下一个VOS/VOP的StartCode

              poslast=pos;

              pos=pos+4;   

       }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MPEG4 基础 简介 I帧 P帧 B