视频流中的I,P,B帧介绍
首先我们需要理解,每一个帧都代表着一个静止的图像。在我们实际传输视频流中,我们会想尽办法,通过各种算法来减少数据的容量,这里最为常见的为IPB(Intra coded frames, Predicted pictures, and Bi-directional predictive pictures)。
首先我们分别对IPB进行了解
- 接下来我们按从I–>P–>B的结构分别详细介绍各自的特点。
- 压缩的基本思想:帧内压缩和帧间压缩。 其次,时间相关性的统计分析:统计的结果表明,在间隔1~2帧的图像中,各像素只有10%以下的点,其亮度差值变化超过2%,而色度差值的变化只有1%以下。
采用的压缩方法: 分组:把几帧图像分为一组(GOP),为防止运动变化,帧数不宜取多。
- 定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;
- 预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
- 数据传输:最后将I帧数据与预测的差值信息进行存储和传输。
I帧
- I帧是关键帧,属于帧内压缩。就是和AVI的压缩是一样的。
- I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
特点:(I帧:帧内编码帧 )
- 它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
- 解码时仅用I帧的数据就可重构完整图像;
- I帧描述了图像背景和运动主体的详情;
- I帧不需要参考其他画面而生成;
- I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
- I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
- I帧不需要考虑运动矢量;
- I帧所占数据的信息量比较大。
P帧
- P是向前搜索的意思。B是双向搜索。他们都是基于I帧来压缩数据。
- P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
特点:( P帧:前向预测编码帧)
P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。
- P帧是I帧后面相隔1~2帧的编码帧;
- P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
- 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
- P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
- P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
- 由于P帧是参考帧,它可能造成解码错误的扩散;
- 由于是差值传送,P帧的压缩比较高。
B帧
- B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些,有兴趣可以看看我上面提供的资料),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累~。
特点:( B帧:双向预测内插编码帧)
B帧的预测与重构
B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。
- B帧是由前面的I或P帧和后面的P帧来进行预测的;
- B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
- B帧是双向预测编码帧;
- B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
- B帧不是参考帧,不会造成解码错误的扩散。
IPB全角度分析
- 从上面的解释看,我们知道I和P的解码算法比较简单,资源占用也比较少,I只要自己完成就行了,P呢,也只需要解码器把前一个画面缓存一下,遇到P时就使用之前缓存的画面就好了,如果视频流只有I和P,解码器可以不管后面的数据,边读边解码,线性前进,大家很舒服。
但网络上的电影很多都采用了B帧,因为B帧记录的是前后帧的差别,比P帧能节约更多的空间,但这样一来,文件小了,解码器就麻烦了,因为在解码时,不仅要用之前缓存的画面,还要知道下一个I或者P的画面(也就是说要预读预解码),而且,B帧不能简单地丢掉,因为B帧其实也包含了画面信息,如果简单丢掉,并用之前的画面简单重复,就会造成画面卡(其实就是丢帧了),并且由于网络上的电影为了节约空间,往往使用相当多的B帧,B帧用的多,对不支持B帧的播放器就造成更大的困扰,画面也就越卡。
一般平均来说,I的压缩率是7(跟JPG差不多),P是20,B可以达到50,可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。
当然,切换数字电视频道的时候,为啥有一两秒钟的延迟或者出现一顿的现象,看了上文也就清楚明白了。 - 注意:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧,至于图像中的哪一帧是I帧,是随机的,一但确定了I帧,以后的各帧就严格按规定顺序排列。
如何区分IPB帧呢
mpeg4的每一帧开头是固定的:00 00 01 b6,那么我们如何判断当前帧属于什么帧呢?在接下来的2bit,将会告诉我们答案。注意:是2bit,不是byte,下面是各类型帧与2bit的对应关系:
00: I Frame
01: P Frame
10: B Frame
为了更好地说明,我们举几个例子,以下是16进制显示的视频编码:
00 00 01 b6 10 34 78 97 09 87 06 57 87 …… I帧
00 00 01 b6 50 78 34 20 cc 66 b3 89 …… P帧
00 00 01 b6 96 88 99 06 54 34 78 90 98 …… B帧
下面我们来分析一下为什么他们分别是I、P、B帧
//16进制转2进制
0x10 = 0001 0000
0x50 = 0101 0000
0x96 = 1001 0100
大家看红色的2bit,再对照开头说的帧与2bit的对应关系,是不是符合了呢?
下面给出一段c++代码:
switch(buf[i] & (BYTE)0xc0) //取00 00 01 b6的后两个bit
{
case 0x00:
//I Frame
break;
case 0x40:
//P Frame
break;
case 0x80:
//B Frame
break;
default:
break;
}