zoukankan      html  css  js  c++  java
  • (转)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]
  • 相关阅读:
    查看uCOS-II的CPU使用率
    ARM的工作环境和工作模式
    一个简单的 JSON 生成/解析库
    [转] libtool的作用及应用
    Qt 使用 net-snmp 包的过程记录
    Qt 立体水晶按键实现
    xampp 修改 mysql 默认 root 密码
    mint 设置无线 AP
    dpkg 小记
    转-ubuntu清理卸载wine的残余项目
  • 原文地址:https://www.cnblogs.com/lihaiping/p/4241716.html
Copyright © 2011-2022 走看看