之所以写这篇文章是因为有朋友对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. DX9入门笔记1-D3D初始化

    对3D编程期待已久,却一直叶公好龙浅尝辄止.近期在公司实习却无具体的工作安排,琢磨着学习个新的手艺,就又想起了3D Programming.这次从大名鼎鼎的龙书(Introduction to 3D ...

  2. jQuery-1.9.1源码分析系列(一)整体架构

    不废话,直接上关键.这个系列中有好些直接借用别人的资料,我将他们整合在自认为比较合理的地方.所以在此先谢谢那些前辈. 注意:后续系列中jQuery实例多用$(...)来表示 1.    初始化与链式调 ...

  3. CSS清除浮动

    今天看到一篇文章关于清除浮动的,突然间脑袋短路了,咦?为什么要清除浮动?原谅我的无知,搜了下原来是这样,又倒腾出原来的笔记,唉,本来就有记录啊,而且也会经常用到,用的久了连原理都忘了.恩,防止自己再犯 ...

  4. 记一个简单的sql查询

    在我们做各类统计和各类报表的时候,会有各种各样的查询要求.条件 这篇主要记录一个常见的统计查询 要求如下: 统计一段时间内,每天注册人数,如果某天没有人注册则显示为0 现在建个简单的表来试试 建表语句 ...

  5. C#使用资源文件的方法

    其实,对于资源文件的使用,说白点就是通过强制类型转换,将资源文件里的数据强行的转换成你需要的(换种方式说,就是你原来存进去什么,就用什么类型拿出来). 主要通过System.Resources.Res ...

  6. DevExpress ComboBoxEdit 添加值

    今天在使用ComboBoxEdit 这个控件的时候,不知道怎么添加值. 在官网上找到代码.在这里做个记录 ComboBoxEdit combo = new ComboBoxEdit(); ComboB ...

  7. Ajax制作智能提示搜索

    一.效果图: 二.实现过程: 思路: 三.部分代码: html: <div id="searchbox"> <div><input type=&quo ...

  8. Unity3D 5.x 简单实例 - 发射炮弹

    1,下载.安装: http://unity3d.com/cn/get-unity/download/archive 建议直接借助 UnityDownloadAssistant 进行安装,根据需要勾选需 ...

  9. file_get_contents()/file_put_contents()

    PHP file_get_contents() 函数 定义和用法 file_get_contents() 把整个文件读入一个字符串中. 该函数是用于把文件的内容读入到一个字符串中的首选方法.如果服务器 ...

  10. 安卓模拟器genymotion连接eclipse成功但是不显示其中项目

    安卓模拟器困了我两三天了,原装模拟器比较慢,忍受不了,查到安卓模拟器的神器——genymotion 按照网上的步骤一步步都安装完毕,最后打开后发现,genymotion界面里面没有找到新建的工程, 这 ...