1、概述

H264是MPEG-4标准所定义的最新编码格式,同时也是技术含量最高、代表最新技术水平的视频编码格式之一,标准写法应该是H.264。H.264视频格式是经过有损压缩的,但是在技术上尽可能做到降低存储体积下获得较好图象质量和低带宽图像快速传输。

2、相关概念

下图为H.264码流分层

2.1 VCL&NAL

H264 原始码流是由一个接一个 NALU(NAL Unit) 组成,它的功能分为两层,VCL(Video Coding Layer)视频编码层和 NAL(Network Abstraction Layer)网络提取层。

  • VCL:包括核心压缩引擎和块、宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;
  • NAL:负责将 VCL 产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别;

NAL是 H.264 为适应网络传输应用而制定的一层数据打包操作。传统的视频编码算法编完的视频码流在任何应用领域下(无论用于存储、传输等)都是统一的码流模式,视频码流仅有视频编码层 VCL(Video Coding Layer)。而 H.264 可根据不同应用增加不同的 NAL 片头,以适应不同的网络应用环境,减少码流的传输差错。

在 VCL 进行数据传输或存储之前,这些编码的 VCL 数据,被映射或封装进NAL单元(NALU)。

一个 NALU = 一组对应于视频编码的 NALU 头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)

一个原始的 H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是 “00 00 00 01”

实际原始视频图像数据保存在 VCL 分层的 NAL Units 中

2.2 片(slice)

片是 H.264 提出的新概念,实际原始视频图像数据保存在 VCL 层级的 NAL Unit 中,这部分数据在码流中被称作是片(slice)。一个 slice 包含一帧图像的部分或全部数据,换言之,一帧视频图像可以编码为一个或若干个 slice。一个 slice 最少包含一个宏块,最多包含整帧图像的数据。在不同的编码实现中,同一帧图像中所构成的 slice 数目不一定相同。

一个 slice 编码之后被打包进一个 NALU,所以 slice = NALU

那么为什么要设置片呢?

设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差不会传播到其他片中。

在上图中,可以看到每个图像中,若干宏块(Macroblock)被排列成片。一个视频图像可编成一个或更多个片,每片包含整数个宏块(MB),每片至少包含一个宏块。

slice类型

slice 组成

每一个 slice 总体来看都由两部分组成,一部分作为 slice header,用于保存 slice 的总体信息(如当前 slice 的类型等),另一部分为 slice body,通常是一组连续的宏块结构(或者宏块跳过信息)

2.3 宏块(Macroblock)

刚才在片中提到了宏块,那么什么是宏块呢?

宏块是视频信息的主要承载者。一个编码图像通常划分为多个宏块组成.包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中像素阵列。

一个宏块由一个 16×16 亮度像素和附加的一个 8×8 Cb 和一个 8×8 Cr 彩色像素块组成。

2.4 帧(frame)和场(filed)

视频的一场和一帧用来产生一个编码图像,一帧通常是一个完整的图像,当采集视频信号时,如果采用隔行扫描(奇、偶数行),则扫描下来的一帧图像就被分成了两个部分,这每一部分都被称为 [场],根据次序,分为 [顶场] 和 [底场]。

为什么会产生场的概念?

人眼可察觉到的电视视频图像刷新中的闪烁为 0.02 秒,即当电视系统的帧率低于 50 帧/秒,人眼可感觉得出画面的闪烁。常规如 PAL 制式电视系统帧率为 25 帧/秒、NTSC 制式的则为 30 帧/秒,如果采用逐行扫描将不可避免地在视频刷新时产生闪烁现象。而另一方面如果单纯的提高帧率达到避免闪烁刷新效果,则会增加系统的频带宽度。

这便引出了隔行扫描技术及 [场] 的概念

在隔行扫描中,每一帧包含两个场(top field)和(bottom field),其中每个 field 包含一帧中一半数量的水平线,top field 包含所有奇数线,bottom field 则包含所有偶数线。则在电视显示过程中,电子枪每发射一行隔一行—先发射奇数行13579…(top field)回头再发射2468…(bottom field)利用两次扫描来完成一幅图像,因为视觉的滞留性,我们看到的效果是差不多的。如在 NTSC 视频中 frame 的频率为30次/秒而field的频率则为 60 次/秒,大于了人眼可察觉闪烁的频率。

适用类型

2.5 I 帧、P 帧、B 帧与 pts/dts

  • I frame: 自身可以通过视频解压算法解压成一张单独的完整的图片;
  • P frame:需要参考其前面的一个 I frame 或者 B frame 来生成一张完整的图片;
  • B frame: 则要参考其前一个 I 或者 P帧 及其后面的一个 P 帧来生成一张完整的图片;

pts/dts

DTS 与 PTS 的不同:
DTS 主要用户视频的解码,在解码阶段使用。PTS主要用于视频的同步和输出,在 display 的时候使用。再没有 B frame 的时候输出顺序是一样的。

2.6 GOP

GOP 是画面组,一个 GOP 是一组连续的画面。
GOP 一般有两个数字,如 M = 3,N = 12,M 制定 I 帧与 P 帧之间的距离,N 指定两个 I 帧之间的距离。那么现在的 GOP 结构是

I BBP BBP BBP BB I

增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了。

2.7 IDR

一个序列的第一帧叫做 IDR帧(Instantaneous Decoding Refresh,立即解码刷新)。

I 帧和 IDR 帧都是使用帧内预测,本质上是同一个东西,在解码和编码中为了方便,将视频序列中第一个 I 帧和其他 I 帧区分开,所以把第一个 I 帧称作 IDR,这样就方便控制编码和解码流程。

IDR 帧的作用是立刻刷新,使错误不致传播,从 IDR 帧开始,重新算一个新的序列开始编码。

核心作用

H.264 引入 IDR 帧是为了解码的重同步,当解码器解码到 IDR 帧时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会,IDR 帧之后的帧永远不会使用 IDR 之前的图像的数据来解码。

3、H264 码流分层结构

如上图,在 H264 中,句法元素共被组织成:序列、图像(帧)、片、宏块、子宏块五个层次。

句法元素的分层结构有助于更有效地节省码流。例如,在一个图像中,经常会在各个片之间有相同的数据,如果每个片都同时携带这些数据,势必会造成码流的浪费。更为有效的做法是将该图像的公共信息抽取出来,形成图像一级的句法元素,而在片级只携带该片自身独有的句法元素。

4、NALU Header & RBSP 结构

如上图:NALU = NAL Header + RBSP

4.1 NALU Header

前面已经说到,每个 NALU 由一个字节的 Header 和 RBSP(Raw Byte Sequence Payload) 组成。

NALU Header 由三部分组成,forbidden_bit(1bit),nal_ref_idc(2bits)代表优先级,nal_unit_type(5bits)代表该 NALU 的类型。

forbidden_zero_bit

1 bit,H264 规定此位必须为 0

nal_ref_idc

用于表示当前 NALU 的重要性,值越大,越重要。

解码器在解码处理不过来的时候,可以丢掉重要性为 0 的 NALU。

  • nal_ref_idc 不等于 0 时, NAL unit 的内容可能是 SPS/PPS/参考帧 的片
  • nal_ref_idc 等于 0 时,NAL unit 的内容可能是非参考图像的片
  • 当某个图像的片的 nal_ref_id 等于 0 时,该图像的所有片均应等于 0

nal_unit_type

nal_unit_type 是否包含 VCL 层编码数据分为 VCL NAL units 和 non-VCL NAL units;
VCL NAL units 中包含 VCL 层编码输出的数据, 而 non-VCL NAL units 则不包含。

所有的值对于类型如下:

4.2 RBSP

上图是 RBSP 序列举例

上图是 RBSP 的描述

SODB 与 RBSP

SODB 数据比特串 -> 是编码后的原始数据.
RBSP 原始字节序列载荷 -> 在原始编码数据的后面添加了 结尾比特。一个 bit “1” 若干比特 “0”,以便字节对齐。

H264 编解码协议的更多相关文章

  1. ffmpeg H264 编解码配置

    ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) { AVCodec * ...

  2. 转:关于视频H264编解码的应用实现

    转:http://blog.csdn.net/scalerzhangjie/article/details/8273410 项目要用到视频编解码,最近半个月都在搞,说实话真是走了很多弯路,浪费了很多时 ...

  3. 【MINA】用protobuf做编解码协议

    SOCKET协议 支持java serial 与 AMF3的混合协议,目前没有基于xml 与 json的实现. 协议说明: * 9个字节协议头+协议体. * * 协议头1-4字节表示协议长度 =协议体 ...

  4. H264 编解码框架简单介绍

    阅读完H264/AVC 编解码器的介绍,脑海中仅仅是留下下面三条: 1.H264并没有明白规定一个编解码器怎样实现,仅仅是规定了一个编码后的视频比特流的句法,和该比特流的解码方法,这个与MPEG 类似 ...

  5. 让WebRTC支持H264编解码

    近期实验了下怎样让WebRTC支持H264编码.记录下,供有须要的人參考. 说明一下,我是在 Ubuntu Server 14.04 下编译的 WebRTC ,使用 native(C++) api 开 ...

  6. 聊聊视频中的编解码器,你所不知道的h264、h265、vp8、vp9和av1编解码库

    你知道FFmpeg吗?了解过h264/h265/vp8/vp9编解码库吗? 我们日常生活中使用最广泛的五种视频编码:H264(AVC).H265(HEVC).vp8.vp9.av1都分别是什么?由哪些 ...

  7. iOS8系统H264视频硬件编解码说明

    公司项目原因,接触了一下视频流H264的编解码知识,之前项目使用的是FFMpeg多媒体库,利用CPU做视频的编码和解码,俗称为软编软解.该方法比较通用,但是占用CPU资源,编解码效率不高.一般系统都会 ...

  8. 视音频编解码基本术语及解释&MediaInfo

    MEDIA INFO 下载: https://mediaarea.net/en/MediaInfo/Download/Windows 摘要:          整理了一些基本视音频术语,用于入门和查询 ...

  9. 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...

随机推荐

  1. 【剑指Offer】数字在排序数组中出现的次数 解题报告(Python)

    [剑指Offer]数字在排序数组中出现的次数 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interv ...

  2. 一个网关服务性能问题的Dump分析

    本篇文章分为三部分,首先简单介绍一下分析的工具Windbg,其次针对一个网关服务性能问题进行逐步刨析,最后针对性能问题的分析总结. 一 Windbg介绍 1.Windbg是个非常强大的调试器,它设计了 ...

  3. Towards Evaluating the Robustness of Neural Networks

    目录 概 主要内容 基本的概念 目标函数 如何选择c 如何应对Box约束 attack attack attack Nicholas Carlini, David Wagner, Towards Ev ...

  4. Linux搜索查找类

    find find将从指定目录下递归地遍历各个子目录,将满足条件的文件或目录显示在终端,如果没有则不显示 基本语法 find 搜索范围 [选项] 选项说明 选项 功能 -name 按照文件名查找 -u ...

  5. java 代理模式 总结

    1.前言 最近舍友去面试遇到了关于java代理模式的问题. 我虽然知道怎么使用,但是没有做过正经的总结,因此有了这篇随笔,好好总结一下三大代理模式底层原理. 事实上,在开发项目的时候,基本用不上代理, ...

  6. Python常用功能函数系列总结(一)

    本节目录 常用函数一:获取指定文件夹内所有文件 常用函数二:文件合并 常用函数三:将文件按时间划分 常用函数四:数据去重 写在前面 写代码也有很长时间了,总觉得应该做点什么有价值的事情,写代码初始阶段 ...

  7. 移动端字体图标不显示的Bug

    用16进制编码的字体图标在部分小米机型显示不正常. 测试机型:小米1,小米1s,小米2浏览器:微信6.1内置浏览器,QQ浏览器 5.7 X5内核字体图标:不显示svg图标:显示正常 以下来自额微信内置 ...

  8. 只需两步在Linux系统安装百度网盘--Ubuntu20

    Linux Ubuntu系统安装百度网盘 百度网盘已支持Linux系统下载和使用.使用Linux系统下载并安装一个百度网盘是非常简单的,只需要以下两个步骤: 第一步 进入官网下载.deb类型的百度网盘 ...

  9. HDU-1004(C语言描述)

    Let the Balloon Rise 输入 输入包含多个测试用例.每个测试用例都以数字 N (0 < N < = 1000) 为起点, 分布的气球总数.下 N 行包含一个颜色.气球的颜 ...

  10. elementui-日期选择器时间清空报错踩坑

    今天在项目中遇到了这个大坑 具体问题:在日期清空时会报错 解决方法:给日期绑定的值添加监听