一、H.264 压缩格式简介
1、流媒体解码流程
流媒体 解码流程 :
- 协议层 : 数据通过 HTTP / RTMP / RTSP / 文件系统协议 进行存储和传输 , 将这些数据 传入 FFmpeg 解复用器 中 ;
- 封装格式层 : 解复用器 将 FLV / MP4 / MKV 等格式解复用 , 通过 解封装 操作 得到 音频流 和 视频流 ;
- 编解码层 : AAC / MP3 格式的 音频数据解码为 PCM 音频采样 , H264 / H265 / MPEG4 格式的视频数据解码为 YUV 或 RGB 原始图像画面 ;
- 媒体播放 : PCM 格式的音频送入 扬声器 / 耳机 等播放设备中进行播放 , YUV / RGB 格式的图像数据送入到屏幕设备中播放 ;
完整流程如下图所示 :
其中涉及到 视频数据 解码 , 目前最流行的 视频压缩格式 就是 H.264 压缩格式 , 下面针对该压缩格式进行解析 ;
2、H.264 压缩格式制定
H.264 又称为 Advanced Video Coding ( AVC ) , 是由
- ITU-T 视频编码专家组 ( VCEG )
- ISO/IEC 动态图像专家组 ( MPEG )
联合开发的一种高效视频压缩标准 , 被广泛应用于 流媒体 传输、存储 和 实时通信 等 领域 ;
3、H.264 压缩格式特点
H.264 视频压缩格式 有 如下 特点 :
- 高压缩效率 : H.264 相较于早期的 MPEG-2 标准 , 在 同等视频质量下 可以 将码率降低 50% 以上 , 可以在 有限的带宽 和 存储空间 中提供了 更高的视觉效果 ;
- 灵活的网络适应性 : H.264 支持 多种传输协议 和 应用场景 , 如 IPTV、视频会议、流媒体、广播和存储等 ;
- 多样化的应用场景 : 支持从 低码率 到高码率 的各种应用场景。
- 高级技术支持 : 包括 帧内预测、帧间预测、CABAC 熵编码、可变块大小运动补偿等多项先进的压缩技术。
4、H.264 压缩格式涉及的主要技术
H.264 压缩格式涉及的主要技术 :
- 帧内预测 ( Intra Prediction ) : 基于当前帧像素的相邻区域 , 进行空间域内的预测 , 提高静态场景的编码效率 ;
- 帧间预测 ( Inter Prediction ) : 基于视频帧之间的时间相关性 , 使用 运动估计 和 补偿 来 减少冗余信息 ;
- 熵编码 ( Entropy Coding ) : 使用 CABAC 或 CAVLC 技术 , 提高压缩率 ;
- CABAC : CABAC 是一种 基于上下文自适应的 二进制算术编码方法 , 通过逐位处理数据 , 实现更高的压缩效率 ; 更高的压缩率 , 但计算复杂度较高 , 适合对压缩效率要求高的场景 , 如 : 蓝光光盘 或 高码率视频 ;
- CAVLC : CAVLC 是一种 基于上下文的自适应变长编码方法 , 通过 变长码表 对数据进行编码 ; 压缩率稍逊于 CABAC , 但复杂度低 , 适合实时编码或资源有限的场景 , 如 : 流媒体 或 硬件限制设备 ;
- 多参考帧 ( Multiple Reference Frames ) : 支持使用多个参考帧 , 增加编码灵活性和效率 ;
- 可变块大小 ( Variable Block Sizes ) : 支持 不同大小的 编码块 , 如 : 16x16、8x8 , 优化运动补偿 ;
二、H.264 编码解析
1、原始视频数据大小
视频的 原始数据 占用的存储空间极大 , 1 分钟的 1920x1080 的 30 FPS 的视频 , 每个像素点使用 RGB 三个字节 , 其占用的存储空间为 :
1920 * 1080 * 3 * 60 * 30 = 11,197,440,000 Byte = 10,935,000 KB = 10,678.71 MB = 10.43 GB
1 分钟的原始视频需要 10GB 的存储空间 , 如果是 3 小时的电影 , 则需要 1.8 TB 的存储空间 , 因此 原始的视频格式 是无法进行存储的 , 必须进行视频压缩 ;
当前最常用的 视频压缩编码格式 就是 H.264 格式 ;
2、H.264 编码原理
视频文件由一系列 图像帧 组成 , 每秒的 帧数 称为 帧率 FPS , 如 : 每秒包含 30 帧 , 帧率为 30 FPS ;
① 空间冗余 - 帧内压缩 ( Intra-frame Compression )
帧内压缩 用于 消除 图像的空间冗余 , 一张 图像帧 内部的元素 具有较高的相似性 , 视频帧被划分为 16×16 的宏块 ;
通过 相似性比较 和 压缩编码 来减少数据冗余 , 每个 16×16 的 宏块 可以根据其相邻像素块的信息 , 通过不同的预测模式 , 如 : 水平、垂直、对角线等 , 生成预测值 , 然后仅对预测值与实际值之间的差异进行编码 ;
这种方法通过 减少空间上的冗余信息 , 实现帧内的高效压缩 ;
② 时间冗余 - 帧间压缩 ( Inter-frame Compression )
帧内压缩 用于 消除 多张图像帧 之间的 时间冗余 , 利用相邻帧之间的相似性进行压缩 ;
帧间压缩 常用如下两种方法 实现 :
- 运动估计 ( Motion Estimation ) : 在 当前帧 中查找 与前后参考帧 对应区域最相似的块 , 并记录偏移量 , 该 偏移量 称为 " 运动矢量 " ;
- 运动补偿 ( Motion Compensation ) : 使用 运动矢量 重建 当前帧 的预测值 , 仅对 预测值 与 实际值 之间的 差异 进行编码 ;
H.264 编码 允许 多个参考帧、可变块大小 , 进一步提高了帧间压缩效率 ;
3、帧间压缩
H.264 视频压缩编码 的 消除 时间冗余 的 帧间压缩 , 采用了 I 帧 / P 帧 / B 帧 策略 实现了 连续帧 之间的压缩 ;
- I 帧 : 帧内编码帧 ( Intra Picture ) 是每个 GOP 画面组 的起始帧 , 经过适度压缩后,作为随机访问的参考点 , 可视为一张独立的图像 ; I 帧的编码结果相当于一张压缩后的图像 , 其自身包含完整的信息 , 无需依赖其他帧 , 通过视频解压算法即可还原为一幅完整的画面 ;
- P 帧 : 前向预测编码帧 ( Predictive-Frame ) , 依赖前面已经编码的 视频帧 的 时间冗余信息 进行压缩传输的 帧 , 又称为 " 预测帧 " ;
- B 帧 : 双向预测帧 ( Bi-directional Predicted Frames ) , 依赖 该帧 前后的 I 帧 或 P 帧 进行编码 , 存储的是 与 前后帧 之间的差异 ;
- 压缩率排序 : B 帧 > P 帧 > I 帧 ;
① B 帧 不能作为 参考帧
在 I 帧 / P 帧 / B 帧 中 , B 帧 的压缩率 是最高的 , 占用空间最小 , 画面质量最低 ; 但是 B 帧 不能用作 参考帧 ;
避免循环依赖 : B 帧 的预测基于 之前的帧 和 之后的帧 , 本身 依赖于其他帧 ; 如果将 B 帧用作参考帧 , 那么它的后续帧解码将形成循环依赖 , 如 : B 帧解码依赖前后帧 , 而后帧又可能依赖于这个 B 帧 , 这样就增加了解码器处理的复杂度 ;
空间优化角度考虑 : B 帧的设计目的是 为了 提高压缩效率 , 如果允许 B 帧作为参考帧 , 需要额外存储其解码结果 , 增加了解码器的内存需求 ;
拉低画质 : B 帧 压缩效率高 , 但是 画面质量低 , 参考 低质量 画面 解码的帧 会拉低视频画质 , 编码器 也会 尽量避免参考 B 帧 ;
② I 帧 / P 帧 / B 帧 参考资料
- 【音视频原理】视频帧的 I P B 帧概念 ① ( 码率 / 帧率 / 分辨率 视频信息 | I 帧 - 内部编码帧 | I 帧 - 关键帧压缩法 | P 帧 - 前向预测帧 )
- 【音视频原理】视频帧的 I P B 帧概念 ② ( B 帧 - 双向内插帧 | 画面组 Group of Pictures 概念 | 各类型帧解码错误影响 | 画面组编解码顺序 | 常用视频压缩算 )
4、H.264 编码结构
H.264 编码格式 提供了 视频编码 和 分片策略 , 编码 按照层级大小 , 分为 五层编码结构 , 从大到小逐层组织 :
- 序列 ( GOP ) : 画面组 , 视频流的 基本组织单位 , 控制帧之间的编码与依赖关系 ;
- 图像 ( Picture ) : 单个图像帧 , 由多个片组成 , 代表视频中的一帧图像 ;
- 片 ( Slice ) : 图像的更小单位 , 便于并行解码和更高容错性 , 每片由一组宏块组成 ;
- 宏块 ( Macroblock ) : 编码过程中的 基本处理单位 , 包含压缩信息 , 通常为 16×16 像素大小 , 由多个 4×4 的子块组成 ;
- 子块 ( Subblock ) : 宏块的细分单位,通常为 4×4 或更小尺寸的块 , 用于更精细的编码处理 , 提升压缩效率 ;
H.264 的 这种 层次化 结构 使得 在视频编码中具备了 高效的压缩能力 和 良好的灵活性 ;
① 序列 ( GOP , Group of Pictures )
序列 是 视频流 中的基本单位 , 通常 由一系列相邻的视频帧组成 , 又称为 GOP 画面组 ( Group of Pictures ) ;
每个 GOP 包含多种类型的帧 , 包括
- I 帧 , 关键帧
- P 帧 , 前向预测帧
- B 帧 , 双向预测帧
I 帧 提供了独立的解码参考 , 而 P 帧和 B 帧则 依赖于其他帧 进行预测 ;
序列作用 : GOP 中定义了 帧之间的 依赖关系 和 编码方式 , 是 解码器 解码视频 的最基本单元 ;
② 图像 ( Picture )
图像 是指视频中的 一帧图像 , 它包含完整的图像数据 , I 帧、P 帧 和 B 帧 都是 图像 ;
每个图像 由多个片 Slice 组成 ;
图像作用 : 图像是一个较大的编码单位 , 其内的片可以独立解码 , 该层次的结构 帮助 视频数据 在 传输和解码 过程中更具灵活性 ;
③ 片 ( Slice )
片 是 图像中的 子单位 , 每个片由 一组宏块 组成 ;
片 根据划分策略 , 片可以分为不同类型 :
- 行片 ( Row Slice ) : 将 图像帧 按行 划分为多个片 的方式 , 每个片通常包含 一行连续的宏块行 ;
- 单片 ( Single Slice ) : 将 整个图像帧作为一个片进行编码 , 不再划分为多个子区域 ;
独立解码 : 片是 H.264 中 支持 并行解码 的最小单元 , 可以使得不同的片在解码时彼此独立 , 从而加速视频的解码过程 , 尤其是在网络丢包或数据错误的情况下 , 每个片可以独立解码 , 不影响其他片 ;
④ 宏块 ( Macroblock )
宏块 是 H.264 编码中的 最基本处理单元 , 通常为 16×16 像素大小 ;
一个宏块 由 多个 4×4 的子块组成 ;
每个宏块包含 亮度 Y 和 色度 U、V 信息 ;
宏块 是 视频压缩 过程中最重要的单元之一 , 每个宏块可以通过 预测、变换、量化 等步骤进行压缩 ;
宏块内的数据 包括
- 帧内预测 ( I 帧 ) 编码信息
- 帧间预测 ( P 帧、B 帧 ) 编码信息
⑤ 子块 ( Subblock )
子块 是 宏块 内的更小单元 , 通常为 4×4 或更小尺寸的块 ; 每个宏块可以进一步被分解成多个子块 , 在进行变换和量化时采用不同的算法 ;
子块用于 更精细 的 压缩处理 , 如 : 通过 细粒度的运动估计 来 优化视频的压缩效率 ;
子块 使得 H.264 编码能够 更好地利用视频帧中的细节 , 减少压缩损失 ;
5、IDR 图像帧
IDR 图像帧 ( Instantaneous Decoder Refresh , 即时解码刷新帧 ) 是 H.264 编码中一种 特殊类型的 I 帧 ( Intra-coded Frame ) ;
IDR 帧 都是 I 帧 , 但是 I 帧 不一定是 IDR 帧 , 二者都包含完整的图像信息 , 可以独立解码而无需依赖其他帧 ;
① IDR 帧 与 I 帧 区别
特性 | IDR 帧 | 普通 I 帧 |
---|---|---|
独立解码 | 是 | 是 |
参考帧刷新 | 清空参考帧缓存 | 不清空,可能依赖之前的参考帧 |
随机访问点 | 是 | 否 |
解码后帧依赖 | 后续帧仅参考当前 GOP 内的帧 | 后续帧可能参考之前 GOP 的帧 |
给定一个帧序列 :
IDR1 P4 B2 B3 P7 B5 I10 B8
- 上述 帧序列 中 , B8 帧 可以跨过 I10 帧 , 参考 前面的 P7 帧 ;
给定一个帧序列 :
IDR1 P4 B2 B3 P7 B5 IDR10 B8
- 上述 帧序列 中 , B8 帧 只能参考 IDR10 帧 , 不能参考 IDR10 帧 之前的 视频帧 ;
- 解码器 遇到 IDR10 帧 , 就会将前面的 参考帧 全部清空 , 不让 后面的 视频帧 参考 IDR 帧 前面的 视频帧 ;
② IDR 帧位置
IDR 帧 通常是 每个 GOP ( 画面组 Group of Pictures ) 的起始帧 , 标志着一个 新的画面组 的开始 ;
IDR 帧 在视频流中 不一定频繁出现 , 具体出现频率由 编码器 的设置决定 , 如 : 每 2 秒插入一个 IDR 帧 ;
频繁插入 IDR 帧会 增加 码流体积 , 但能提供更好的随机访问性能 ;
③ 解码同步与清除参考帧
IDR 帧 主要用于 提供 解码同步点 和 增强容错 能力 , 遇到 IDR 帧后 解码器 立刻执行 重新同步操作 和 清除参考帧 的依赖关系 , 确保后续 视频数据 的 解码独立性 ( 不让后续 B 帧 / P 帧 依赖 IDR 帧前面的帧 ) ;
在 IDR 帧之后的 P 帧和 B 帧 , 只参考当前 GOP 内的帧 , 而不会依赖于 IDR 帧之前的任何帧数据 ;
④ 随机访问点
IDR 帧通常是视频流中的 随机访问点 ( Random Access Point ) , 用户可以从 IDR 帧开始解码和播放视频 , 而无需解码前面的数据 ;
普通 I 帧 不能作为 随机访问点 , 因为后面的 P 帧 或 B 帧 可能回参考 I 帧之前 的 视频帧 ;