MPEG4码流简单分析

来源:互联网 发布:gnuradio ubuntu 编辑:程序博客网 时间:2024/05/21 05:58
分类: 工作随笔 Domain Know How 3187人阅读 评论(6)收藏举报

    测试解码器测试了很久,由于需要将H264MPEG4的码流进行分析和判断,并逐帧输入解码器进行测试,如何正确的分析码流,并将Video送给我们的解码器做Decode的呢?耐着性子找了很多资料,主要也因为我本身对MPEG4H264的码流的格式并不懂,自己在视频编码方面的积累也实在是太少了,所以也确实挺头疼的。后来就直接在网上找是否有对码流的各个部分意义的解释,开始搜索码流中的的StartCode。高兴的是,最终找到了一些有用的讯息,得以继续进行测试代码的撰写。

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

 

MPEG4分析:

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

0x00, 0x00, 0x01, 0xB6作为一个VOP的开始,紧跟着VOP开始的,有一个2bit的标志,用来表示这个Frame到底是一个 I FrameP FrameB Frame抑或是S FrameGMS-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<MAX_HEADERLEN)  

{

//长度小于一定值,则不够一帧大小,表示在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)

             {

                    //判定是IPB ,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/VOPStartCode

             poslast=pos;

             pos=pos+4;   

      }

可以简单拿个图说明一下,下图中,第一个VOS的开头,第二个是一个I Frame

MPEG4二进制码流

by lydia