之所以写这篇文章是因为有朋友对IPB帧的设置比较感兴趣,回复中说得比较简单,因此在这里详细的写一下,虽然说一般情况下我们很少去设置这个IPB帧,不过,如果真的学好了,并且清楚的了解了这个IPB帧的概念和设置后,我们能够在渲染成品的时候更加好的掌控视频的质量与体积。

在说怎么设置之前,我们先了解一下IPB帧的概念,网络上其实蛮多的,我这里稍微做一点自己的改变和理解,这样更加方便我们理解。

首先说到IPB帧,就不得不说一下帧内压缩和帧间压缩:关于压缩,我想不需要做更多的解释,简单点,就是为了在保证我们可以接受的质量前提下,尽可能缩小原始音视频的体积,这样的一个过程就是压缩。

帧内压缩(Intraframe compression),也称之为空间压缩。就是指在压缩时,只计算单帧画面内的信息,不考虑前后帧的关联,单帧压缩会丢掉该帧内无用的信息或者根据设置,丢掉更多我们认为不重要的画面信息,因此,相对而言,帧内压缩可以极大程度保留画面清晰度、色彩范围以及其他信息。同时,因为帧内压缩是对单帧画面的完整压缩,不牵涉到其他相邻的帧画面,因此在播放器解码时,所需要消耗的资源也是比较小的。因为其不考虑与其他帧的冗余信息,因此,和我们一般常用的静态图像压缩类似,属于有损压缩。

帧间压缩(Interframe compression),也称之为时间压缩。是指在压缩时,需要计算相邻帧之间的画面信息差异,即在相邻的单帧画面中,会存在冗余信息,压缩这些冗余信息就可以进一步提高压缩量,减少压缩比。采用帧间压缩的方式,就是专门用于处理连续图像的一种编码压缩,这样的压缩,会导致画面信息更多的丢失,但是,却可以极大的减小音视频文件的体积,所以,我们现在大部分使用的压缩编码,都是以帧间压缩为主,帧内压缩为辅的方式。

那么,提到了帧间压缩,我们就会牵涉到最常见的IPB帧的概念:
I帧表示关键帧,I帧画面完整保留,只采取帧内压缩,解码时只需要本帧数据就可以完成(因为包含完整画面)。
P帧是向前预测编码帧(也叫差别帧),表示这一帧跟之前的一个关键帧(或P帧)的差别,P帧没有完整画面数据,只有与前一帧的画面差别的数据,因此解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。
B帧是双向预测编码帧(双向差别帧),B帧记录的是当前帧与前后帧的差别,换言之,解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。

其中P帧与B帧的压缩都基于I帧,显而易见B帧压缩率最高,但是解码时CPU会不断的进行前后帧的对比,因此会消耗大量的系统资源。

我们经常会在摄像机或者记录下的视频文件中看到自己拍摄视频所采用的压缩算法,常见的有All-I,以及IPB。
如果视频流只采用了All-I压缩(全部帧都是I帧关键帧),那么解码器可以不管后面的数据,边读边解码,线性前进。如果视频流压缩采用了IPB,有B帧,则需要缓存前面和当前的视频帧,待后面视频帧获得后,再进行解码。

在当前的网络流媒体中,为什么很多网络直播会有延时,很大程度上就是因为IPB的压缩算法,在网络条件较好的地区,延时会少很多,或许只有几秒钟,网络条件差的地方,以及计算机配置不太好的服务器和播放端,延迟的时间就会比较长。

说了以上那么多,相信有的人已经一头雾水了,其实关于IPB帧,他们自己还有很多专属的特点,这里不一一赘述。接下来,我们引入一个概念:GOP(帧组)。

简单的理解GOP就是两个I帧之间的间隔。
我们可以打一个比方,假设我们现在有一个每秒15帧,时长3秒的动画视频,我们设定第一帧为I帧关键帧,设定第15帧为P帧差别帧,那么,中间第2帧~第14帧则为B帧双向差别帧。这总共15帧就组成了一个GOP帧组,也即是说,这个时长3秒的动画视频,一共有3个GOP。
在流媒体服务器上,都会设定是否在客户请求时直接将缓存数据发送给客户,还是等到有I帧的时候再发送。如果设定的是有I帧的时候发送,那么播放客户端只有在获得I帧后才会有完整的视频流,客户端缓冲时间较长,但是延迟至少是一个GOP,套用刚才的例子就是1秒。如果直接发送,不等I帧,客户端得到的画面会残缺,但是延迟则较低。

当然,实际的情况中我们可以自行设定多少才是一个完整的GOP,一般情况下,一个GOP,短的可以设置5~6秒钟,即第1帧为I帧,第5帧为P帧,2、3、4帧为B帧,那么在这样的设置下,我们即可以得到一个压缩比较高,但是画面信息也相对更完整的视频流。

我这里使用Vegas中的Mpeg-2的IPB帧设置来进行参考。(其他的编码虽然在Vegas中没有IPB帧的设置,但并非不存在,只是因为IPB是Mpeg-2的标准压缩方式)
<ignore_js_op>

通常的情况下,每12~15帧就必须要传输一个I帧的信息,因此,在Vegas中默认的I帧参数是12,同时,在压缩计算时,如果画面场景进行了切换(或者转场),那么则该帧必须定义为I帧。当然,你可以进行自定义。
默认情况下,B帧的长度是2。此时,整个GOP帧组的顺序为IBBPBBPBBPBB,此后继续重复IBBPBBPBBPBB。
那么在这里,我们就可以对这两个参数进行更改和设置,如果我们设置I帧为5,B帧设置为3的话,那么就如同我刚才所说的,第1帧为I帧,第5帧为P帧,2、3、4帧为B帧,顺序为IBBBP,这5帧成为一个完整的GOP帧组,之后类推。

那么,说到这里,我相信很多人应该能够理解了,有时候两个同样的视频文件,码率一样,时长一样,分辨率一样,但是体积不一样,很大程度上是因为GOP(或者IPB)的不一样,试想一下,一个视频中有大量的I帧存在,而另一个则没有,那么,同样的压缩,所产生的视频文件体积当然会有不同。
同样,我们过去常说的一个文件压缩多次之后,画面质量下降,体积变小,也正是由于IPB的设置所导致的。

现在我们引申一下,谈谈的恒定比特率和动态比特率:
恒定比特率就是从视频一开始到结束,每一秒的码率都是恒定不变的,这样,不管画面信息是复杂还是简单,转场有多少,码率都是同一个,能够保证画面始终是我们想要的质量,但是文件体积很大。
动态比特率则计算在画面信息量大,动态场景多的地方使用码率最大值,画面信息简单,转场不复杂的地方使用最小值,其他地方计算平均值进行浮动,这样虽然某些画面在转场或者信息量大的地方可能会产生马赛克等画面残次,但文件体积可以压缩控制。

那么问题来了,在压缩的时候,计算机又是如何知道该在什么地方采用最大值或者最小值呢?依旧是刚才的图:
<ignore_js_op>

根据我刚才讲解的IPB以及GOP的知识,就可以知道,计算机是根据IPB和GOP的设置来进行动态比特率的调整的。
而动态比特率中的二次编码,指的就是在第一次计算过程中,只计算画面的IPB帧设置与画面信息,而不进行编码压缩,完成第一次编码后第二次才进行视频压缩,二次编码的压缩速度远慢于一次编码,但是同样的设置,二次编码得到的画面质量会高于一次编码。

根据我从业多年的经验,经常会遇到客户有这样的要求:体积控制在150M以内,分辨率720*576或720*480,帧数25帧,格式Mpg、Mov、Rmvb、Wmv。
针对这样的需求,往往半小时左右时长的DVD是很难控制在150M以内的,当然,如果控制在100M一下,大家可以想象一下Mpg-2这个格式下,低码率的动态画面是有多么不堪入目,此时我们就不能选择Mpg-2这样采用帧间压缩的视频格式,而需要使用Wmv等采用帧内压缩的格式,因为这样的格式虽然在单帧画面中可能没有很高的清晰度,但是,能保证的是画面与画面之间流畅的衔接而不会出现马赛克这样的情况。

说到这里,我做个小的总结:
现在我们做片子,已经很少会牵涉到IPB帧的设置了一般默认就可以,而恒定码率和动态码率的设置,根据现在的全国网速来看,其实也已经没有太大的关系。当年网络流媒体需要设置动态码率,是因为带宽普遍只有2M甚至更低,而这个参数在如今的网速面前,其实已经没有什么必要,因此,一般采用默认的IPB,恒定码率,就已经可以满足在线视频的高清流畅播放了。

转载自:

  [原创] 关于IPB帧与恒定比特率、动态比特率的详解

关于IPB帧与恒定比特率、动态比特率的详解的更多相关文章

  1. 【VB技巧】VB静态调用与动态调用dll详解

    本文“[VB技巧]VB静态调用与动态调用dll详解”,来自:Nuclear'Atk 网络安全研究中心,本文地址:http://lcx.cc/?i=489,转载请注明作者及出处! [[请注意]]:在以下 ...

  2. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  3. 【转】java的动态代理机制详解

    java的动态代理机制详解   在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们 ...

  4. java的动态代理机制详解-----https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

    java的动态代理机制详解-----https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

  5. 动态内存管理详解:malloc/free/new/delete/brk/mmap

    c++ 内存获取和释放 new/delete,new[]/delete[] c 内存获取和释放 malloc/free, calloc/realloc 上述8个函数/操作符是c/c++语言里常用来做动 ...

  6. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  7. java的动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  8. JNI_Android项目中调用.so动态库实现详解

    转自:http://www.yxkfw.com/?p=7223 1. 在Eclipse中创建项目:TestJNI 2. 新创建一个class:TestJNI.java package com.wwj. ...

  9. JNI_Android项目中调用.so动态库实现详解【转】

    转自 http://www.cnblogs.com/sevenyuan/p/4202759.html 1. 在Eclipse中创建项目:TestJNI 2. 新创建一个class:TestJNI.ja ...

随机推荐

  1. (八)WebGIS中栅格图层的设计

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.    前言 我们在上一章里了解到WebGIS中栅格图层的本质—— ...

  2. 1.Java基础之System对象

    毕向东老师Java基础学习笔记——System对象 今天学习Java中的System对象后,感觉这个对象对我们主要有以下几点用处. 1.获取当前操作系统版本和类型. 2.获取当前操作系统的path中的 ...

  3. 流行ORM产品优缺点分析--EntityFramework、NHibernate、PetaPoco

    什么是ORM? ORM的全称是Object Relational Mapping,即对象关系映射.它的实现思想就是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的操 ...

  4. 基于CkEditor实现.net在线开发之路(5)列表页面开发

    这章主要讲解利用控件开发列表页面,我们先从最简单的列表页面开始讲解,这个列表只有一个列表展示.具体开发步骤请看下面动态图 由上动态图可以看出,开发一个简单的列表只有两步, 第一步:拖拽查询控件,设置好 ...

  5. 【C#进阶系列】28 基元线程同步构造

    多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗 ...

  6. python之网络编程

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...

  7. tet

    施大峰[[昂司法部]]... [[分公司电饭煲]]

  8. Java关于Properties用法(二)——替换配置文件中的参数

    上一章讲了配置文件的基本用法,虽然上一章已经可以解决一些需求,但还不些不足之处.假如,配置文件里面的字符串有一部分需要经常变动,另外一些不需要,上一章的方法就不方便了,所以这章主要讲如何在配置文件中使 ...

  9. Understanding glibc malloc【待译】

    今天尝试用Valgrind调试程序时,发现堆和栈的一些问题没有理解透彻,于是Google了下"Memory Layout C",接着就通过Memory Layout of C Pr ...

  10. SQL注入—我是如何一步步攻破一家互联网公司的

    最近在研究Web安全相关的知识,特别是SQL注入类的相关知识.接触了一些与SQL注入相关的工具.周末在家闲着无聊,想把平时学的东东结合起来攻击一下身边某个小伙伴去的公司,看看能不能得逞.不试不知道,一 ...