I帧、P帧、B帧的概述

来源:互联网 发布:excel数组公式 编辑:程序博客网 时间:2024/06/03 21:01

关于视频帧类型的一点总结,如有不足之处,敬请指出:)

1.IPB帧概念简述

视频压缩中,每帧代表一幅静止的图像。而在实际压缩时,会采取各种算法减少数据的容量,其中IPB就是最常见的。简单地说,I帧是关键帧,属于帧内压缩,解码时单独的该帧便可完成解码;P帧为向前预测编码帧,即P帧解码时需要参考前面相关帧的信息才能解码;B帧为双向预测编码帧,解码时既需要参考前面已有的帧又需要参考后面待解码的帧;他们都是基于I帧来压缩数据。

I帧表示关键帧,I帧画面完整保留,解码时只需要本帧数据就可以完成(因为包含完整画面)。

P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)

B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别,换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

因此,I帧和P帧的解码算法比较简单,资源占用也比较少,I帧只要自己完成就行了,至于P帧,也只需要解码器把前一个画面缓存一下,遇到P帧时就使用之前缓存的画面就行。如果视频流只有IP,解码器可以不管后面的数据,边读边解码,线性前进。如果视频流还有B帧,则需要缓存前面和当前的视频帧,待后面视频帧获得后,再解码。

 

2.IPB帧特点分析

I帧特点:

1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;

2.解码时仅用I帧的数据就可重构完整图像;

3.I帧描述了图像背景和运动主体的详情;

4.I帧不需要参考其他画面而生成;

5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);

6.I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I;

7.I帧不需要考虑运动矢量;

8.I帧所占数据的信息量比较大。

 

P帧特点:
1.P
帧是I帧后面相隔1~2帧的编码帧;

2.P帧采用运动补偿的方法传送它与前面的IP帧的差值及运动矢量(预测误差);

3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;

4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P;

5.P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;

6.由于P帧是参考帧,它可能造成解码错误的扩散;

7.由于是差值传送,P帧的压缩比较高。

 

B帧特点
1.B
帧是由前面的IP帧和后面的P帧来进行预测的;

2.B帧传送的是它与前面的IP帧和后面的P帧之间的预测误差及运动矢量;

3.B帧是双向预测编码帧;

4.B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;

5.B帧不是参考帧,不会造成解码错误的扩散。

 

3.IPB帧的判断

不同视频编码格式有不同的帧类型判断方法。

MPEG4视频中,I帧、P帧、B帧的判定MPEG4的每一帧开头是固定的00 00 01 b6格式,接下来的2bit分别代表着不同类型的视频帧。00代表I Frame01代表 P Frame10代表 B Frame

通过代码判断的方法如下:

//寻找00 00 01 b6的下一个bit所在的索引值

static char*Find_VOP_Start(unsigned char *addrp, unsigned int FindSizes)

{

   int i = 0;

   while(i < FindSizes)

   {

       if(addrp[i] == 0x00)

           if(addrp[i + 1] == 0x00)

               if(addrp[i + 2] == 0x01)

                   if(addrp[i + 3] == 0xB6)

                       break;

       i++;

   }

   if(i < FindSizes - 4)

       return addrp + i + 4;

   else

       return 0;

}

//打印该帧的类型

unsigned int *p;

p=(int*)Find_VOP_Start(inbuf,recv_size);

 switch((*p) & 0xC0)

       {

           case 0x00:

               fprintf(stdout,"The typeof frame is:I\n");// I Frame

               break;

           case 0x40:

               fprintf(stdout,"The typeof frame is:P\n");// P Frame

               break;

           case 0x80:

               fprintf(stdout,"The type of frame is:B\n");// B Frame

               break;

           default:

               fprintf(stdout,"No properframe !\n");

               exit(1);

       }

如果是MPEG2视频,则先找到00 00 01 00,然后根据其后的3bit来判断,001I帧,011B帧,010P帧,判断方法和MPEG4的判断方法完全相同,不同的是在于相关的类型标识比特位。

如果是H.264视频,要先把H264ES流数据解析出来,然后分析出每一个NALNetwork Abstract Layer,网络抽象层),再解析出哪些NAL为一个Frame,最后解析Slice类型,根据Slice类型就可以判断这个FrameIPB类型。判断方法较MPEG2MPEG4复杂。

原创粉丝点击