本文主要介绍一种非常流行的视频编码:H.264

计算一下:10秒钟1080p(1920x1080)、30fps的YUV420P原始视频,需要占用多大的存储空间?

  • (10 * 30) * (1920 * 1080) * 1.5 = 933120000字节 ≈ 889.89MB
  • 可以看得出来,原始视频的体积是非常巨大的

由于网络带宽和硬盘存储空间都是非常有限的,因此,需要先使用视频编码技术(比如H.264编码)对原始视频进行压缩,然后再进行存储和分发。H.264编码的压缩比可以达到至少是100:1。

简介

H.264,又称为MPEG-4 Part 10,Advanced Video Coding

  • 译为:MPEG-4第10部分,高级视频编码
  • 简称:MPEG-4 AVC

H.264是迄今为止视频录制、压缩和分发的最常用格式。截至2019年9月,已有91%的视频开发人员使用了该格式。H.264提供了明显优于以前任何标准的压缩性能。H.264因其是蓝光盘的其中一种编解码标准而著名,所有蓝光盘播放器都必须能解码H.264。

编码器

H.264标准允许制造厂商自由地开发具有竞争力的创新产品,它并没有定义一个编码器,而是定义了编码器应该产生的输出码流。

x264是一款免费的高性能的H.264开源编码器。x264编码器在FFmpeg中的名称是libx264

AVCodec *codec = avcodec_find_encoder_by_name("libx264");

解码器

H.264标准中定义了一个解码方法,但是制造厂商可以自由地开发可选的具有竞争力的、新的解码器,前提是他们能够获得与标准中采用的方法同样的结果。

FFmpeg默认已经内置了一个H.264的解码器,名称是h264

AVCodec *codec1 = avcodec_find_decoder_by_name("h264");

// 或者
AVCodec *codec2 = avcodec_find_decoder(AV_CODEC_ID_H264);

编码过程与原理

H.264的编程过程比较复杂,本文只介绍大体的框架和脉络,具体细节就不展开了。

大体可以归纳为以下几个主要步骤:

  • 划分帧类型
  • 帧内/帧间编码
  • 变换 + 量化
  • 滤波
  • 熵编码

划分帧类型

有统计结果表明:在连续的几帧图像中,一般只有10%以内的像素有差别,亮度的差值变化不超过2%,而色度的差值变化只在1%以内。

GOP

于是可以将一串连续的相似的帧归到一个图像群组(Group Of Pictures,GOP)。

GOP中的帧可以分为3种类型:

  • I帧(I Picture、I Frame、Intra Coded Picture),译为:帧内编码图像,也叫做关键帧(Keyframe)

    • 是视频的第一帧,也是GOP的第一帧,一个GOP只有一个I帧
    • 编码
      • 对整帧图像数据进行编码
    • 解码
      • 仅用当前I帧的编码数据就可以解码出完整的图像
    • 是一种自带全部信息的独立帧,无需参考其他图像便可独立进行解码,可以简单理解为一张静态图像
  • P帧(I Picture、I Frame、Predictive Coded Picture),译为:预测编码图像
    • 编码

      • 并不会对整帧图像数据进行编码
      • 以前面的I帧或P帧作为参考帧,只编码当前P帧与参考帧的差异数据
    • 解码
      • 需要先解码出前面的参考帧,再结合差异数据解码出当前P帧完整的图像
  • B帧(B Picture、B Frame、Bipredictive Coded Picture),译为:前后预测编码图像
    • 编码

      • 并不会对整帧图像数据进行编码
      • 同时以前面、后面的I帧或P帧作为参考帧,只编码当前B帧与前后参考帧的差异数据
      • 因为可参考的帧变多了,所以只需要存储更少的差异数据
    • 解码
      • 需要先解码出前后的参考帧,再结合差异数据解码出当前B帧完整的图像

不难看出,编码后的数据大小:I帧 > P帧 > B帧。

在较早的视频编码标准(例如MPEG-2)中,P帧只能使用一个参考帧,而一些现代视频编码标准(比如H.264),允许使用多个参考帧。

GOP的长度

GOP的长度表示GOP的帧数。GOP的长度需要控制在合理范围,以平衡视频质量、视频大小(网络带宽)和seek效果(拖动、快进的响应速度)等。

  • 加大GOP长度有利于减小视频文件大小,但也不宜设置过大,太大则会导致GOP后部帧的画面失真,影响视频质量

  • 由于P、B帧的复杂度大于I帧,GOP值过大,过多的P、B帧会影响编码效率,使编码效率降低

  • 如果设置过小的GOP值,视频文件会比较大,则需要提高视频的输出码率,以确保画面质量不会降低,故会增加网络带宽

  • GOP长度也是影响视频seek响应速度的关键因素,seek时播放器需要定位到离指定位置最近的前一个I帧,如果GOP太大意味着距离指定位置可能越远(需要解码的参考帧就越多)、seek响应的时间(缓冲时间)也越长

GOP的类型

GOP又可以分为开放(Open)、封闭(Closed)两种。

  • Open

    • 前一个GOP的B帧可以参考下一个GOP的I帧
  • Closed
    • 前一个GOP的B帧不能参考下一个GOP的I帧
    • GOP不能以B帧结尾

需要注意的是:

  • 由于P帧、B帧都对前面的参考帧(P帧、I帧)有依赖性,因此,一旦前面的参考帧出现数据错误,就会导致后面的P帧、B帧也出现数据错误,而且这种错误还会继续向后传播

  • 对于普通的I帧,其后的P帧和B帧可以参考该普通I帧之前的其他I帧

在Closed GOP中,有一种特殊的I帧,叫做IDR帧(Instantaneous Decoder Refresh,译为:即时解码刷新)。

  • 当遇到IDR帧时,会清空参考帧队列
  • 如果前一个序列出现重大错误,在这里可以获得重新同步的机会,使错误不会继续往下传播
  • 一个IDR帧之后的所有帧,永远都不会参考该IDR帧之前的帧
  • 视频播放时,播放器一般都支持随机seek(拖动)到指定位置,而播放器直接选择到指定位置附近的IDR帧进行播放最为便捷,因为可以明确知道该IDR帧之后的所有帧都不会参考其之前的其他I帧,从而避免较为复杂的反向解析

帧内/帧间编码

I帧采用的是帧内(Intra Frame)编码,处理的是空间冗余。

P帧、B帧采用的是帧间(Inter Frame)编码,处理的是时间冗余。

划分宏块

在进行编码之前,首先要将一张完整的帧切割成多个宏块(Macroblock),H.264中的宏块大小通常是16x16。

宏块可以进一步拆分为多个更小的变换块(Transform blocks)、预测块(Prediction blocks)。

  • 变换块的尺寸有:16x16、8x8、4x4

  • 预测块的尺寸有:16×16、16×8、8×16、8×8、8×4、4×8、4×4

帧内编码

帧内编码,也称帧内预测。以4x4的预测块为例,共有9种可选的预测模式。

利用帧内预测技术,可以得到预测帧,最终只需要保留预测模式信息、以及预测帧与原始帧的残差值。

编码器会选取最佳预测模式,使预测帧更加接近原始帧,减少相互间的差异,提高编码的压缩效率。

帧间编码

帧间编码,也称帧间预测,用到了运动补偿(Motion compensation)技术。

编码器利用块匹配算法,尝试在先前已编码的帧(称为参考帧)上搜索与正在编码的块相似的块。如果编码器搜索成功,则可以使用称为运动矢量的向量对块进行编码,该向量指向匹配块在参考帧处的位置。

在大多数情况下,编码器将成功执行,但是找到的块可能与它正在编码的块不完全匹配。这就是编码器将计算它们之间差异的原因。这些残差值称为预测误差,需要进行变换并将其发送给解码器。

综上所述,如果编码器在参考帧上成功找到匹配块,它将获得指向匹配块的运动矢量和预测误差。使用这两个元素,解码器将能够恢复该块的原始像素。

如果一切顺利,该算法将能够找到一个几乎没有预测误差的匹配块,因此,一旦进行变换,运动矢量加上预测误差的总大小将小于原始编码的大小。

如果块匹配算法未能找到合适的匹配,则预测误差将是可观的。因此,运动矢量的总大小加上预测误差将大于原始编码。在这种情况下,编码器将产生异常,并为该特定块发送原始编码。

变换与量化

接下来对残差值进行DCT变换(Discrete Cosine Transform,译为离散余弦变换)。

规格

H.264的主要规格有:

  • Baseline Profile(BP)

    • 支持I/P帧,只支持无交错(Progressive)和CAVLC
    • 一般用于低阶或需要额外容错的应用,比如视频通话、手机视频等即时通信领域
  • Extended Profile(XP)
    • 在Baseline的基础上增加了额外的功能,支持流之间的切换,改进误码性能
    • 支持I/P/B/SP/SI帧,只支持无交错(Progressive)和CAVLC
    • 适合于视频流在网络上的传输场合,比如视频点播
  • Main Profile(MP)
    • 提供I/P/B帧,支持无交错(Progressive)和交错(Interlaced),支持CAVLC和CABAC
    • 用于主流消费类电子产品规格如低解码(相对而言)的MP4、便携的视频播放器、PSP和iPod等
  • High Profile(HiP)
    • 最常用的规格
    • 在Main的基础上增加了8x8内部预测、自定义量化、无损视频编码和更多的YUV格式(如4:4:4)
      • High 4:2:2 Profile(Hi422P)
      • High 4:4:4 Predictive Profile(Hi444PP)
      • High 4:2:2 Intra Profile
      • High 4:4:4 Intra Profile
    • 用于广播及视频碟片存储(蓝光影片),高清电视的应用

【秒懂音视频开发】23_H.264编码的更多相关文章

  1. 【秒懂音视频开发】14_AAC编码

    AAC(Advanced Audio Coding,译为:高级音频编码),是由Fraunhofer IIS.杜比实验室.AT&T.Sony.Nokia等公司共同开发的有损音频编码和文件格式. ...

  2. 【秒懂音视频开发】02_Windows开发环境搭建

    音视频开发库的选择 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:MediaPlayer.Med ...

  3. 【秒懂音视频开发】26_RTMP服务器搭建

    从本节开始,正式开启流媒体相关的内容. 流媒体 基本概念 流媒体(Streaming media),也叫做:流式媒体. 是指将一连串的多媒体数据压缩后,经过互联网分段发送数据,在互联网上即时传输影音以 ...

  4. 【秒懂音视频开发】18_详解YUV

    本文的主角是多媒体领域非常重要的一个概念:YUV. 简介 YUV,是一种颜色编码方法,跟RGB是同一个级别的概念,广泛应用于多媒体领域中. 也就是说,图像中每1个像素的颜色信息,除了可以用RGB的方式 ...

  5. 【秒懂音视频开发】05_Qt开发基础

    控件的基本使用 为了更好地学习Qt控件的使用,建议创建项目时先不要生成ui文件. 打开mainwindow.cpp,在MainWindow的构造函数中编写界面的初始化代码. 窗口设置 MainWind ...

  6. 【秒懂音视频开发】12_播放WAV

    对于WAV文件来说,可以直接使用ffplay命令播放,而且不用像PCM那样增加额外的参数.因为WAV的文件头中已经包含了相关的音频参数信息. ffplay in.wav 接下来演示一下如何使用SDL播 ...

  7. 【秒懂音视频开发】21_显示BMP图片

    文本的主要内容是:使用SDL显示一张BMP图片,算是为后面的<播放YUV>做准备. 为什么是显示BMP图片?而不是显示JPG或PNG图片? 因为SDL内置了加载BMP的API,使用起来会更 ...

  8. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  9. WebRTC 音视频开发

    WebRTC 音视频开发 webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...

随机推荐

  1. k8s多集群配置管理平台

    k8s多集群配置管理平台 临时集群特性 模拟生产环境 整体环境说明 内网:10.17.1.44 [root@localhost account-server]# kubectl get nodes N ...

  2. HTML5-本地存储浅谈

    Web Storage是HTML5里面引入的一个类似于cookie的本地存储功能,可以用于客户端的本地存储 sessionStorage && localStorage session ...

  3. 深度学习---1cycle策略:实践中的学习率设定应该是先增再降

    深度学习---1cycle策略:实践中的学习率设定应该是先增再降 本文转载自机器之心Pro,以作为该段时间的学习记录 深度模型中的学习率及其相关参数是最重要也是最难控制的超参数,本文将介绍 Lesli ...

  4. 2.Python进程间的通信之队列(Queue)和生产者消费者模型

    一.队列 1.1 概念介绍-----multiprocess.Queue 创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递. Queue([maxsize] ...

  5. C++ Primer Plus(第6版)中文版电子版awz+epub+mobi三版

    电子书资源:C++ Primer Plus(第6版)中文版 书籍简介:   C++是在C语言基础上开发的一种集面向对象编程.通用编程和传统的过程化编程于一体的编程语言,是C语言的超集.<C++ ...

  6. Digit Generator UVA - 1583

    ​ For a positive integer N, the digit-sum of N is defined as the sum of N itself and its digits. Whe ...

  7. 号外号外!DevUI Admin V1.0 发布啦!

    4月是鸟儿的月份,是木棉花的月份,是 DevUI Admin 发布的月份. 广受大家期待的 DevUI Admin 终于迎来了第一个开源 Angular 版本! DevUI Admin 是一个企业级中 ...

  8. HUAWEI防火墙双出口据链路带宽负载分担

    组网图形 组网需求 通过配置根据链路带宽负载分担,使流量按照带宽的比例分担到各链路上,保证带宽资源得到充分利用. 如图1所示,企业分别从ISP1和ISP2租用了一条链路,ISP1链路的带宽为100M, ...

  9. Java文档注释全攻略

    注释:注释起到对代码标注和解释的作用,如果你去看看JDK源码,会发现他们有许多的注释,而且注释是比代码还要多的,可见为代码添加注释是非常重要的,写好注释能让别人更加容易看懂你的代码,注释可以分为以下三 ...

  10. php文件的自动加载

    <?php spl_autoload_register(function ($class_name) { require_once $class_name . '.php'; });