深入浅出理解视频编码H264结构(内涵福利)

2023-11-09

转自:https://www.jianshu.com/p/9522c4a7818d

在国内直播"欣欣向荣"(ps: 其实大多都亏钱,为的就是炒概念)的年代,相信很多小伙伴也投入了技术的浩瀚大洋当中(ps: 其实就是搬砖),日复一日,音/视频的神秘面纱开始让更多的小伙伴扯下,而本博主,也只是刚窥探门道,慢慢摸索。好了,废话不扯,我们今天就来说说我们经常在视频编码当中用到的 H.264编码格式 的结构,相信 H.264 这个东西很多小伙伴都不陌生了,也有着自己的理解,但这东西颇为巨大,里面算法千千万万,博主也不会讲太高深的东西,只是让各位小伙伴慢慢理解理解 H.264的主体机构,如果没有兴趣的小伙伴请绕道,如果有技术大牛,请指正本博主那愚钝的脑袋。

首先来一段大家都熟悉的官方话来介绍一下 H.264

H.264: H.264/AVC项目的目的是为了创建一个比以前的视频压缩标准,在更低的比特率的情况下依然能够提供良好视频质量的标准(如,一半或者更少于MPEG-2,H.263,或者MPEG-4 Part2 )。同时,还要不会太大的增加设计的复杂性。
优势:
1)网络亲和性,即可适用于各种传输网络
2)高的视频压缩比,当初提出的指标是比 H.263,MPEG-4,约为它们的 2 倍,现在都已基 实现;

那么很明显,什么时候需要到压缩呢?当然是文件体积太大的时候啦,我们想想,所谓的视频,就是像小时候的连环画一样,在一秒内翻过 24 张以上的图片,就感觉图像是连续的了,这就是视频的原理。但是大家有没有想过,一张图片有多大呢?我们的屏幕分辨率按 1280 * 720 算的话,一秒钟的视频大概就 2.64 MB 了,大家想想,我们大部分的小伙伴为了下载个小嗨片省吃俭用才开了个 1M 的网线,然后连个直播都看不了是什么感觉。那肯定不能这样了,所以我们要进行压缩,而 H.264 不仅压缩比比较高,对网络的兼容性也非常好,所以大多数人做直播也就选择了 H.264 作为编码格式了。

编码流程:
那么 H.264 其编解码流程是怎么样的呢?其实可以主要分为 5 部分: 帧间和帧内预测(Estimation)、变换(Transform)和反变换、量化(Quantization)和反量化、环路滤波(Loop Filter)、熵编码(Entropy Coding)。
看起来很高深的样子,实际上也是很高深的样子,因为这里面包含着许许多多的算法和专业知识,这里我们就不做过多的讲解,有兴趣的同学可以上网翻翻,够你看到睡觉的了。H.264详细文档


原理简介

H.264 原始码流(又称为裸流),是有一个接一个的 NALU 组成的,而它的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL, Network Abstraction Layer)。
VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据 序列。在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元(以下简称 NALU,Nal Unit) 中。每个 NALU 包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组 对应于视频编码的 NALU 头部信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾 比特。一个 bit“1”若干比特“0”,以便字节对齐。

NAL 单元排列

上图中的 NALU头 + RBSP 就相当与一个 NALU (Nal Unit), 每个单元都按独立的 NALU 传送。 其实说白了,H.264 中的结构全部都是以 NALU 为主的,理解了 NALU,就理解 H.264 的结构了。


一帧图片跟 NALU 的关联 :

究竟 NALU 是怎么由一帧图片变化而来的呀,H.264究竟为什么这么神奇?

一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了,我们可以来看看 NALU 跟片的关系(slice)。

图片编码后

NALU 结构

小伙伴们要明白,片(slice)的概念不同与帧(frame),帧(frame)是用作描述一张图片的,一帧(frame)对应一张图片,而片(slice),是 H.264 中提出的新概念,是通过编码图片后切分通过高效的方式整合出来的概念,一张图片至少有一个或多个片(slice)。

上图中可以看出,片(slice)都是又 NALU 装载并进行网络传输的,但是这并不代表 NALU 内就一定是切片,这是充分不必要条件,因为 NALU 还有可能装载着其他用作描述视频的信息。


什么是切片(slice)?

片的主要作用是用作宏块(Macroblock)的载体(ps:下面会介绍到宏块的概念)。片之所以被创造出来,主要目的是为限制误码的扩散和传输。
如何限制误码的扩散和传输?
每个片(slice)都应该是互相独立被传输的,某片的预测(片(slice)内预测和片(slice)间预测)不能以其它片中的宏块(Macroblock)为参考图像。

那么片(slice)的具体结构,我们用一张图来直观说明吧:

我们可以理解为一 张/帧 图片可以包含一个或多个分片(Slice),而每一个分片(Slice)包含整数个宏块(Macroblock),即每片(slice)至少一个 宏块(Macroblock),最多时每片包 整个图像的宏块。

上图结构中,我们不难看出,每个分片也包含着头和数据两部分:
1、分片头中包含着分片类型、分片中的宏块类型、分片帧的数量、分片属于那个图像以及对应的帧的设置和参数等信息。
2、分片数据中则是宏块,这里就是我们要找的存储像素数据的地方。

什么是宏块?

宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。
组成部分:一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个 8×8 Cr 彩色像素块组成。每个图象中,若干宏块被排列成片的形式。

我们先来看看宏块的结构图:

从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern、Quantization Parameter、像素的亮度和色度数据集等等信息。


切片(slice)类型跟宏块类型的关系

对于切片(slice)来讲,分为以下几种类型:

0 P-slice. Consists of P-macroblocks (each macro block is predicted using one reference frame) and / or I-macroblocks.
1 B-slice. Consists of B-macroblocks (each macroblock is predicted using one or two reference frames) and / or I-macroblocks.
2 I-slice. Contains only I-macroblocks. Each macroblock is predicted from previously coded blocks of the same slice.
3 SP-slice. Consists of P and / or I-macroblocks and lets you switch between encoded streams.
4 SI-slice. It consists of a special type of SI-macroblocks and lets you switch between encoded streams.

I片:只包 I宏块,I 宏块利用从当前片中已解码的像素作为参考进行帧内预测(不能取其它片中的已解码像素作为参考进行帧内预测)。

P片:可包 P和I宏块,P 宏块利用前面已编码图象作为参考图象进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即 16×16、16×8、8×16 或 8×8 亮度像素块(以及附带的彩色像素);如果选了 8×8 的子宏块,则可再分成各种子宏块的分割,其尺寸为 8×8、8×4、4×8 或 4×4 亮度像素块(以及附带的彩色像素)。

B片:可包 B和I宏块,B 宏块则利用双向的参考图象(当前和 来的已编码图象帧)进行帧内预测。

SP片(切换P):用于不同编码流之间的切换,包含 P 和/或 I 宏块

SI片:扩展档次中必须具有的切换,它包 了一种特殊类型的编码宏块,叫做 SI 宏块,SI 也是扩展档次中的必备功能。


整体结构
通过剖析了这么多个小零件,是时候个大家一个世界地图了,
那么我们的 NALU 整体结构可以呼之欲出了,以下就引用 H.264 文档当中的一幅图了


其实 H.264 的码流结构并没有大家想的那么复杂,编码后视频的每一组图像(GOP,图像组)都给予了传输中的序列(PPS)和本身这个帧的图像参数(SPS),所以,我们的整体结构,应该如此:

GOP (图像组)主要用作形容一个 i 帧 到下一个 i 帧之间的间隔了多少个帧,增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了。


主题外:(未完待续)

那么,NALU 头部中的类型确定着什么信息呢?
我们首先来看看 NALU 中究竟有哪几种类型,我们来看看 H.264 中源码对 nal_unit_type_e 中的定义:

enum nal_unit_type_e
{
NAL_UNKNOWN = 0, // 未使用
NAL_SLICE = 1, // 不分区、非 IDR 图像的片(片的头信息和数据)
NAL_SLICE_DPA = 2, // 片分区 A
NAL_SLICE_DPB = 3, // 片分区 B
NAL_SLICE_DPC = 4, // 片分区 C
NAL_SLICE_IDR = 5, /* ref_idc != 0 / // IDR 图像中的片
NAL_SEI = 6, /
ref_idc == 0 */ // 补充增强信息单元

  •  

参数集是 H.264 标准的一个新概念,是一种通过改进视频码流结构增强错误恢复能力的方法。
NAL_SPS = 7, // 序列参数集 (包括一个图像序列的所有信息,即两个 IDR 图像间的所有图像信息,如图像尺寸、视频格式等)
NAL_PPS = 8, // 图像参数集 (包括一个图像的所有分片的所有相关信息, 包括图像类型、序列号等,解码时某些序列号的丢失可用来检验信息包的丢失与否)

  • NAL_AUD = 9, // 分界符
    NAL_FILLER = 12, // 填充(哑元数据,用于填充字节)
    /* ref_idc == 0 for 6,9, 10 (表明下一图像为 IDR 图像),11(表明该流中已没有图像),12 */
    };
    ps: 以上括号()中的为类型描述

上面NALU类型当中,分片/切片(slice)的概念我们都已经很清楚了,但是用 NALU 作载体的还有 SEI、SPS、PPS 等等。

今天我们不一一聚述这些类型对整个流程的作用了,我们挑出两个符合我们今天主题的类型来讲,PPS 和 SPS。


那么今天我们讲的 H.264 的码流结构相信大家都有个大概轮廓的了解了,总结的一句话就是:

H.264 中,句法元素共被组织成 序列、图像、片、宏块、子宏块五个层次。

希望大家用心体会,毕竟手工打字和作图不易,大家能关注的关注,能有闲钱的打赏一个,能有赞的赞一下嘛



作者:Abson在简书
链接:https://www.jianshu.com/p/9522c4a7818d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入浅出理解视频编码H264结构(内涵福利) 的相关文章

  • MySQL开启远程访问权限

    默认情况下 MySQL只允许本地登录 即只能在安装MySQL环境所在的主机下访问 但是在日常开发和使用中 我们经常需要访问远端服务器的数据库 此时就需要开启服务器端MySQL的远程连接权限 1 生成环境 连接MySQL 2 查看MySQL当
  • 最言简意赅的strftime和strptime区分方式

    最近时常处理金融数据 最绕不过的就是对各种日期格式进行处理 其中用得最多的就是striptime和striftime 之前每用一次都得查一下用法 这次干脆完全弄清楚然后记下来 以下是最言简意赅的区分方式 strptime 将字符串转换为日期

随机推荐

  • 某团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    转载 最近网上出现一个美团面试题 一个线程OOM后 其他线程还能运行吗 我看网上出现了很多不靠谱的答案 这道题其实很有难度 涉及的知识点有jvm内存分配 作用域 gc等 不是简单的是与否的问题 由于题目中给出的OOM java中OOM又分很
  • 谭铁牛院士:向生物学习 开启模式识别新突破

    人们在观察事物或现象的时候 常常要把各个相似的但又不完全相同的事物或现象组成一类 例如一个数字有不同的写法 对一个人来说 某一种写法虽然没有见过 但大脑却能自动将这个字识别出来 这种模式识别行为虽然人们早已司空见惯 在中国科学院院士谭铁牛看
  • 前端学习历程

    前言 还记得刚接触前端应该是两年前了吧 我就顺着回忆 慢慢写下我对前端的学习路程以及一些资源 初入坑 html css基础 这个是学习前端最基础的部分了 一开始看的是W3cschool 先看其中的html和css基础部分 一些常用标签 以及
  • Python常用的第三方库汇总【推荐】

    Python常用的第三方库汇总 pymysql 操作MySQL数据库 Flask 一个 Python 后端开发的微型框架 numpy 进行科学计算所需的基础包 pillow 非常好用的图像处理库 opencv python 图像处理库 Ma
  • google扫码库barcode-scanning的使用

    一 加入barcode scanning库 捆绑模式扫码 implementation com google mlkit barcode scanning 17 1 0 二 编写扫码分析类 用于分析扫码数据并回调方法返回结果 package
  • DuiLib使用教程之二---测试工程

    DuiLib测试工程 以下内容为原创 欢迎转载 转载请注明 来自试着不呼吸的博客 http blog csdn net haiqiang softwo article details 21485283 通过上节 http blog csdn
  • 短视频APP是如何开启你的美好生活的?

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯视频云终端团队发表于云 社区专栏 常青 2008 年毕业加入腾讯 一直从事客户端研发相关工作 先后参与过 PC QQ 手机QQ QQ物联 等产品项目 目前在腾讯视频云团队负
  • 多态和虚函数的基本概念和用法

    C 多态 多态按字面的意思就是多种形态 当类之间存在层次结构 并且类之间是通过继承关联时 就会用到多态 C 多态意味着调用成员函数时 会根据调用函数的对象的类型来执行不同的函数 多态的优点 代码组织结构清晰 可读性强 利于前期和后期的扩展以
  • steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。

    前言 时不可以苟遇 道不可以虚行 今天的的前言诗句特地百度搜索了一下 诗句大概的意思是 时机是不可能随便就能遇到的 道路也要一步一步踏实地行走 象征着好运的诗句 之所以特地去找这样意思的诗句 主要的原因是 今天就是四六级考试 想给自己带来一
  • 利用Python(netCDF4库)读取.nc文件(NetCDF气象数据文件)的基本操作

    NetCDF network Common Data Form 网络通用数据格式是一种面向数组型并适于网络共享的数据的描述和编码标准 目前 NetCDF广泛应用于大气科学 水文 海洋学 环境模拟 地球物理等诸多领域 用户可以借助多种方式方便
  • LeetCode--初级算法--字符串类算法

    反转字符串 题目 编写一个函数 其作用是将输入的字符串反转过来 示例 1 输入 hello 输出 olleh 示例 2 输入 A man a plan a canal Panama 输出 amanaP lanac a nalp a nam
  • flask配置https协议

    感谢https blog csdn net qq 33934427 article details 127456673 文中多有参考再实践 一 要用https协议需要有ca证书 在windows10先下载windows版本openssl 地
  • uni-app (路由)

    介绍 uni app页面路由为框架统一管理 开发者需要在pages json里配置每个路由页面的路径和页面样式 类似的小程序在app json中配置页面路由相同 所以uni app的路由用法与Vue Router不同 如仍希望采用Vue R
  • Android12及所有版本解决没有system读写权限(只需要magisk面具)

    通过magisk挂载文件的方式来修改system 不用解锁system或挂载读写 前提条件 你要确保你已经正确刷入了Magisk 刷面具保姆级别教程 举一反三 多种手机通用 这个方法实际上就相当于刷模块来达到修改的目的 本文只是给小白普及一
  • 时间同步服务chrony的简单配置

    一 chrony服务器的简介 chrony是一个开源自由的网络时间协议 NTP 的客户端和服务器软软件 它能让计算机保持系统时钟与时钟服务器 NTP 同步 因此让你的计算机保持精确的时间 Chrony也可以作为服务端软件为其他计算机提供时间
  • vue-router安装失败

    当安装vue router遇到以下问题 npm ERR code ERESOLVE npm ERR ERESOLVE unable to resolve dependency tree npm ERR npm ERR While resol
  • 食品PC端的轮播图的文字和图片怎么修改

  • C# Winform 窗体传值 利用委托 子窗体传值给父窗体

    常用的Winform窗体传值有两种方式 1 更改Form designer cs文件 将控件的设为Public 供子窗体访问 在designer cs文件的最后 找到你的控件声明 private System Windows Forms T
  • Qt程序打包发布方法(使用官方提供的windeployqt工具)

    Qt程序打包发布方法 使用官方提供的windeployqt工具 Qt 官方开发环境使用的动态链接库方式 在发布生成的exe程序时 需要复制一大堆 dll 如果自己去复制dll 很可能丢三落四 导致exe在别的电脑里无法正常运行 因此 Qt
  • 深入浅出理解视频编码H264结构(内涵福利)

    转自 https www jianshu com p 9522c4a7818d 在国内直播 欣欣向荣 ps 其实大多都亏钱 为的就是炒概念 的年代 相信很多小伙伴也投入了技术的浩瀚大洋当中 ps 其实就是搬砖 日复一日 音 视频的神秘面纱开