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;
}
相关文章推荐
- tornado简单项目简介以及基础知识(包括错误类型解释十)
- MySQL Cluster基础知识简介以及基本参数介绍
- MySQL Cluster基础知识简介以及基本参数介绍
- jquery 的基础知识,以及和Javascript的区别
- C基础知识-函数指针以及使用
- 一、Docker 知识框架以及入门基础
- memcached系列之1:memcached基础知识简介(为什么要使用memcached做缓存服务器)
- MFC基础知识(一)——文档视图类指针获取、逻辑与设备坐标以及OnDraw
- redis的安装以及基础知识
- Linux基础命令以及基础知识
- 07--MySQL自学教程:DQL(Data Query Language:数据库查询语言)简介、基础查询、条件查询、模糊查询以及排序(一)
- Linux系统基础知识(二)基于linux系统下的用户管理操作以及文件操作补充
- 无线WiFi以及WLAN技术基础知识介绍
- Java基础知识_ArrayList和HashSet的比较,以及HashCode方法
- 股票入门基础知识22:财务健康比率——判断公司实力
- 计算机的基础知识(计算机简介)
- Linux基础知识学习(二)----SZ/RZ命令讲解以及在secureCRT使用SFTP上传文件的讲解
- OpenGL ES学习总结:基础知识简介
- Java基础知识强化72:正则表达式之判断功能(手机号码判断 和 校验邮箱)
- FTP服务系列一FTP的基础知识以及服务器端的配置