(转)MPEG4码流简单分析

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

 

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

今天就把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开头的函数:

  1. static unsigned char *Find_VOP_Start(unsigned char *addrp, unsigned int FindSizes) 
  2.        while(pos < FindSizes) 
  3.        { 
  4.               if(addrp[pos] == 0x00) 
  5.                      if(addrp[pos + 1] == 0x00)   
  6.                             if(addrp[pos + 2] == 0x01)   
  7.                                    if(addrp[pos + 3] == 0xB0) 
  8.                                           break;//判断是否是VOS头; 
  9.                if(addrp[pos] == 0x00) 
  10.                      if(addrp[pos + 1] == 0x00)   
  11.                              if(addrp[pos + 2] == 0x01)   
  12.                                     if(addrp[pos + 3] == 0xB6) 
  13.                                          break;//判断是否是VOP头 
  14.              pos++; 
  15.        } 
  16.        if(pos< FindSizes - 4) 
  17.        {     
  18.               return addrp+pos+4; 
  19.        } 
  20.        else   
  21.               return NULL; 

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

  1. size_t nRead = fread(lpSrc, 1, lSize, fp); 
  2. fseek(fp, 0, SEEK_SET); 
  3. while (!feof(fp)) 
  4. unsigned char *p=Find_VOP_Start(lpSrc,lSize); 
  5. if (pos)    //pos为文件当前指针 
  6. length=pos-poslast+header;   //每帧长度为两个StartCode之间的字节数; 
  7. if (length<MAX_HEADERLEN)   
  8. //长度小于一定值,则不够一帧大小,表示在I frame前面的VOS,VO,VOL头 
  9. header=length; 
  10. else 
  11. header=0; 
  12. if (0==(nInput=fread(buffer,1,length,fp))) break; //读取一帧大小数据, 
  13. //调用解码器接口,进行解码测试操作;…… 
  14. if (p==NULL) break; 
  15. //判定VOS是哪种profile 
  16. if (*(p-1)==0xB0) 
  17. if (*p==0xF5)  printf("VOS Header start,Advanced Simple Profile level 5!/n"); 
  18. else if (*p==0x1) printf("VOS Header start,Simple Profile level 1!/n"); 
  19. else if (*p==0x2)  printf("VOS Header start,Simple Profile level 2/n!"); 
  20.      …… 
  21. else  printf("VOS Header Start,Other profile@level/n!"); 
  22. if (*(p-1)==0xB6) 
  23. //判定是I,P,B ,S  Frame 
  24. if ((*p & 0xC0)==0x00)printf("VOP-I frame # %d, ", frames++); 
  25. else if ((*p & 0xC0)==0x40) printf("VOP-P frame # %d, ", frames++); 
  26. else if ((*p & 0xC0)==0x80) printf("VOP-B frame # %d, ", frames++); 
  27. else if ((*p & 0xC0)==0xC0) printf("VOP-S frame # %d, ", frames++); 
  28. else   printf("VOP-unknown type frame # %d, ",frames++); 
  29. //继续查找下一个VOS/VOP的StartCode 
  30. poslast=pos; 
  31. pos=pos+4;    

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

MPEG4二进制码流

by lydia

(axdc_qa_team)
 
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201111/15315.html]
原文地址:https://www.cnblogs.com/lihaiping/p/4241716.html