把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. {
  3. while(pos < FindSizes)
  4. {
  5. if(addrp[pos] == 0x00)
  6. if(addrp[pos + 1] == 0x00)
  7. if(addrp[pos + 2] == 0x01)
  8. if(addrp[pos + 3] == 0xB0)
  9. break;//判断是否是VOS头;
  10. if(addrp[pos] == 0x00)
  11. if(addrp[pos + 1] == 0x00)
  12. if(addrp[pos + 2] == 0x01)
  13. if(addrp[pos + 3] == 0xB6)
  14. break;//判断是否是VOP头
  15. pos++;
  16. }
  17. if(pos< FindSizes - 4)
  18. {
  19. return addrp+pos+4;
  20. }
  21. else
  22. return NULL;
  23. }

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

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

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

by lydia

(axdc_qa_team)

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

(转)MPEG4码流简单分析的更多相关文章

  1. H264码流打包分析(精华)

    H264码流打包分析 SODB 数据比特串-->最原始的编码数据 RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若 ...

  2. H264码流打包分析

    转自:http://www.360doc.com/content/13/0124/08/9008018_262076786.shtml   SODB 数据比特串-->最原始的编码数据 RBSP ...

  3. AAC 码流信息分析

    AAC在对PCM数据进行编码时,使用window取出1024或128个数据进行MDCT转换到频域. Window的相关信息记录在ics_info中: 关于ics_info中各个字段的含义如下 wind ...

  4. p2p技术之n2n源码核心简单分析一

    首先在开篇之前介绍下内网打洞原理 场景:一个服务器S1在公网上有一个IP,两个私网机器C1,C2 C1,C2分别由NAT1和NAT2连接到公网,我们需要借助S1将C1,C2建立直接的TCP连接,即由C ...

  5. aac adts & LATM封装码流分析

    本文继续上一篇文章的内容,介绍一个音频码流处理程序.音频码流在视频播放器中的位置如下所示. 本文中的程序是一个AAC码流解析程序.该程序可以从AAC码流中分析得到它的基本单元ADTS frame,并且 ...

  6. 视音频数据处理入门:AAC音频码流解析

    ===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...

  7. 视音频数据处理入门:H.264视频码流解析

    ===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...

  8. H264码流中SPS PPS详解<转>

    转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...

  9. h264码流分析及其工具

    总的来说H264的码流的打包方式有两种,一种为annex-b byte stream format的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开头的3~4个字节是H264的start_co ...

随机推荐

  1. 正则表达式写法:Java和Js比较

    1.表示数字 Java:\\d              Js: \d 比如密码写法,Java中:(^[a-zA-Z\\d]{6,20}$),Js中:/^[a-zA-Z\d]{6,20}$/

  2. 关于K8s集群器日志收集的总结

    本文介绍了kubernetes官方提供的日志收集方法,并介绍了Fluentd日志收集器并与其他产品做了比较.最后介绍了好雨云帮如何对k8s进行改造并使用ZeroMQ以消息的形式将日志传输到统一的日志处 ...

  3. 如何设置Docker容器中Java应用的内存限制

    如果使用官方的Java镜像,或者基于Java镜像构建的Docker镜像,都可以通过传递 JAVA_OPTS 环境变量来轻松地设置JVM的内存参数.比如,对于官方Tomcat 镜像,我们可以执行下面命令 ...

  4. 处理“位域”枚举类型变量的几个例子

    所谓的位域就是说利用一个整形数字二进制下不同的标志位来使一个枚举变量可以记录多个信息. 例如现在有一个定义好的位域枚举: [Flags] public enum FlagEnum { 我是第一个=, ...

  5. Python文件遍历二种方法

    分享下有关Python文件遍历的两种方法,使用的OS模块的os.walk和os.listdir实现. 关于Python的文件遍历,大概有两种方法,一种是较为便利的os.walk(),还有一种是利用os ...

  6. Servlet与WebService关系

    转自:http://www.cnblogs.com/cy163/archive/2008/04/16/1155767.html 其实从实现的效果上,它们是很相似的         相同点:     客 ...

  7. 翻翻git之---效果鲜明的类ViewPager库 ConvenientBanner(对图片载入部分进行改动)

    转载请注明出处:王亟亟的大牛之路 昨天写了篇基础的View绘制的内容貌似观众老爷们不怎么喜欢.那再这里再安利下自己定义View时.用到Paint Canvas的一些温故.讲讲用路径绘画实现动画效果(基 ...

  8. PHP 对 memcache操作类

    <span style="font-size:18px;">class myMemcache { private $memcache; /** * 一般建议这2个值做成 ...

  9. ADO.NET 连接方式进行数据库访问

    转自:http://www.cnblogs.com/oneword/archive/2010/09/10/1823414.html 连接到数据源 连接到数据源需要使用两步: 1.创建连接字符串 2.使 ...

  10. ServiceMetadataBehavior 的 HttpsGetEnabled 属性设置为 True,而 HttpsGetUrl 属性是相对地址,但没有 https 基址

    WCF 发布,本机正常,服务器报错,信息如下: ServiceMetadataBehavior 的 HttpsGetEnabled 属性设置为 True,而 HttpsGetUrl 属性是相对地址,但 ...