专栏首页字节流动音视频基础:H264 各种概念

音视频基础:H264 各种概念

原文链接: https://juejin.cn/post/6983879143632928782

背景

最近团队需要熟悉一下音视频相关的知识,所以最近回顾了一下H264的相关名词解释

温故而知新,然后发现H264好多流程以前还是不太熟悉。后续会用对比的方式学习H265。

H264

H.264,又称为MPEG-4第10部分,高级视频编码(AVC),也称为H.264或MPEG-4第10部分,高级视频编码(MPEG-4 AVC),是基于面向块,运动补偿的整数DCT编码的视频压缩标准。

截至2019年9月,它是视频内容的记录,压缩和分发的最常用格式,截止到2019年9月,已有91%的视频行业开发人员使用了该格式。它支持高达8K UHD的分辨率

其实H264是VCEG和MPEG(第十部)的一部分开发的,所以常用于指代此标准的名称有H.264/AVC,AVC/H.264,H.264/MPEG-4 AVC,或MPEG-4/H.264 AVC。

简单来说,H264就是对于视频原始数据尽可能去掉冗余数据。

  • 时间冗余
  • 空间冗余
  • 知识冗余
  • 结构冗余
  • 视觉冗余
  • 信息熵冗余

H264编码流程

相关概念

序列

H264编码标准中所遵循的理论依据个人理解成:参照一段时间内相邻的图像中,像素、亮度与色温的差别很小。

所以当面对一段时间内图像我们没必要去对每一幅图像进行完整一帧的编码,而是可以选取这段时间的第一帧图像作为完整编码,而下一幅图像可以记录与第一帧完整编码图像像素、亮度与色温等的差别即可,以此类推循环下去。

什么叫序列呢?上述的这段时间内图像变化不大的图像集我们就可以称之为一个序列。序列可以理解为有相同特点的一段数据。

但是如果某个图像与之前的图像变换很大,很难参考之前的帧来生成新的帧,那么就结束上一个序列,开始下一段序列。重复上一序列的做法,生成新的一段序列。

帧类型

H264协议内定义了三种帧,分别是I帧、B帧与P帧

  • I帧。关键帧,采用帧内压缩技术
  • P帧。向前参考帧,压缩时只参考前一帧,属于帧间压缩技术
  • B帧。双向参考帧,压缩时既参考前一帧,也参考后一帧,属于帧间压缩技术。

其中,帧内预测压缩:解决的是空域数据冗余问题,比如删除一副图里人眼不是很敏感的颜色光亮等。

帧间预测压缩:解决的是时域数据冗余问题,随着时间轴的推移,删除重复的数据。

整数离散余弦变换(DCT):将空间上的相关性变为频域上无关的数据然后进行量化。

GOP

两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧。(图像组)主要用作形容一个 i 帧 到下一个 i 帧之间的间隔了多少个帧,增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量。

IDR帧(关键帧)

在编码解码中为了方便,将GOP中首个I帧要和其他I帧区别开,把第一个I帧叫IDR,这样方便控制编码和解码流程,所以IDR帧一定是I帧,但I帧不一定是IDR帧;

IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始算新的序列开始编码。I帧有被跨帧参考的可能,IDR不会。

作用:

H.264引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。

这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

H.264编码分层

VLC(Video Coding Layer)层是对核心算法引擎、块、宏块及片的语法级别的定义,负责有效表示视频数据的内容,最终输出编码完的数据SODB。

NALU(Network Abstraction Layer Units)定义了片级以上的语法级别(如序列参数集参数集和图像参数集,针对网络传输,后面会描述到),负责以网络所要求的恰当方式去格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。

H264结构中,一个视频图像编码后的数据叫做一帧,一帧由一个片(slice)或多个片组成,一个片由一个或多个宏块(MB)组成,一个宏块由16x16的YUV数据组成。宏块作为H264编码的基本单位。

NALU type

在H.264中,量化参数分3个级别给出:图像参数集(pps)、片头(slice_header)、宏块(mb)。参数使用指数哥伦布码方式保存。

Exp-Golomb指数哥伦布码

指数哥伦布码(Exponential-Golomb)属于熵编码,属于无损编码

H.264中使用的是0阶指数哥伦布编码,编码方式如下:

以待编码码号code_num = 3为例:

第一步:将code_num +1, 即3+1 = 4

第二步:将4写为二进制的形式:100

第三步:计算100的比特个数为3,在100前面写(3-1)个0,得到编码码字:00100

0阶指数哥伦布码如下所示:

1 => 10 => 010  
2 => 11 => 011  
3 => 100 => 00100  
4 => 101 => 00101
5 => 110 => 00110
6 => 111 => 00111
7 => 1000 => 0001000
8 => 1001 => 0001001

NALU、RBSP、EBSP、SODB

H264裸流中,可以提取到一个个的NALU,并且解析出NALU Header,NALU Header是占一个字节。下面我们就从NALU Header的下一个字节开始,分析NALUE Placeholder部分。

NALU的Placeholder涉及到三个重要的名词,分别为EBSP、RBSP和SODB。

  • SODB 数据比特串-->最原始的编码数据
  • RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐。
  • EBSP 扩展字节序列载荷-- >在RBSP基础上填加了仿校验字节(0X03)它的原因是:NALU的起始码为0x000001或0x00000001,同时H264规定,当检测到0x000000时,也可以表示当前NALU的结束。 那这样就会产生一个问题,就是如果在NALU的内部,出现了0x000001或0x000000时,就需要使用“防止竞争”这样一种机制,当编码器编码完一个NAL时,应该检测NALU内部,是否出现0x000000、0x000001、0x000002、0x000003。 当检测到它们存在时,编码器就在最后一个字节前,插入一个新的字节:0x03。比如:0x00000300、0x00000301、0x00000302、0x00000303。 这样一来,当我们拿到EBSP时,就需要检测EBSP内是否有序列:0x000003,如果有,则去掉其中的0x03。这样一来,我们就能得到原始字节序列载荷:RBSP。

公式可以这样看:

NALU = NALU Header(1 bytes) + EBSP

RBSP = SODB  + RBSP trailing bits

RBSP = EBSP - 0x03

其中RBSP trailing bits用于对齐字节数,因为SODB是最原始的编码数据,所以需要使用trailing bits来对齐字节数。

SPS/PPS

  • SPS:Sequence Parameter Set,序列参数集

NAL uint_type=7 包括了一个图像序列的所有信息(包含的是针对一连续编码视频序列的参数,如标识符seq_parameter_set_id、帧数及POC的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识等)

  • PPS

PPS:Picture Parameter Set,图像参数集 NAL uint_type=8 包括了一个图像所有片的信息(对应的是一个序列中某一副图像或者某几幅图像,参数如标识符pic_parameter_set_id、可选的seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等)

视频冗余

前面说到一些名词之后初步认识了H264大概的结构,现在我们这边探讨的是,对于各种冗余的剔除。

帧内压缩

帧内预测

人眼对图象都有一个识别度,人的眼睛对图像的低频特性比如物体的总体亮度之类的信息很敏感,而对图像中的高频细节信息不敏感。所以基于一些研究,可以将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。

帧内压缩类似于图片压缩,跟这一帧的前面(或后面)一帧(或几帧)无关,由当前帧中,已编码的部分来推测当前待编码的这一部分数据是什么。

一幅图像被划分好宏块后,对每个宏块可以进行 9 种模式的预测。找出与原图最接近的一种预测模式。然后,将原始图像与帧内预测后的图像相减得残差值。

再将我们之前得到的预测模式信息一起保存起来,这样我们就可以在解码时恢复原图了。

DCT 变换和量化

这里不展开说,详细算法和过程可以google一下。

帧间压缩

运动估计

  • 运动估计 基本思想是将图像序列的每一帧分成许多互不重叠的宏块,并认为宏块内所有象素的位移量都相同,然后对每个宏块到参考帧某一给定特定搜索范围内根据一定的匹配准则找出与当前块最相似的块,即匹配块,匹配块与当前块的相对位移即为运动矢量。 视频压缩的时候,只需保存运动矢量和残差数据就可以完全恢复出当前块。得到运动矢量的过程被称为运动估计。
  • 运动估计算法

是视频压缩编码的核心算法之一。高质量的运动估计算法是高效视频编码的前提和基础。其中块匹配法(BMA, Block Match Algorithm)由于算法简单和易于硬件实现,被广泛应用于各视频编码标准中。

块匹配法的基本思想是先将图像划分为许多子块,然后对当前帧中的每一块根据一定的匹配准则在相邻帧中找出当前块的匹配块,由此得到两者的相对位移,即当前块的运动矢量。

在H.264标准的搜索算法中,图像序列的当前帧被划分成互不重叠16×16大小的子块,而每个子块又可划分成更小的子块,当前子块按一定的块匹配准则在参考帧中对应位置的一定搜索范围内寻找最佳匹配块,由此得到运动矢量和匹配误差。运动估计的估计精度和运算复杂度取决于搜索策略和块匹配准则。

这里使用H.264推荐算法UMHexagonS(Unsymmetrical-cross Multi-Hexagon-grid Search)作为DSP实现的算法参考,与FS算法比较,它在保证可靠搜索精度的前提下大幅降低搜索复杂度。同时使用绝对差和(SAD, the Sum of Absolute Difference)标准作为匹配准则,它具有便于硬件实现的优点。

运动补偿

  • 运动补偿

运动补偿是通过先前的局部图像来预测、补偿当前的局部图像,它是减少帧序列冗余信息的有效方法。

运动补偿的基本原理是,当编码器对图像序列中地第N帧进行处理时,利用运动补偿中地核心技术-运动估值ME(Motion Estimation),得到第N帧得预测帧N´。在实际编码传输时,并不总时传输第N帧,而是第N帧和其预测帧N´得差值△。

如果运动估计十分有效,△中得概率基本上分布在零附近,从而导致△比原始图像第N帧得能量小得多,编码传输△所需得比特数也就少得多。

运动补偿的步骤如下:

(1)图像分割为静止得和运动的两部分,估计物体得位移向量(位移值)。

(2)按照估计得到的位移向量取得前一帧的图像数据。

(3)通过使用预测滤波器,得到前一帧图像数据的预测像素。

最后得到残差还需要DCT一下。

环路滤波

简单地说一下。

  • 产生原因

各个块变换量化过程相对独立,因此引入的量化误差大小及其分布特性相互独立,导致相邻块边界的不连续;运动补偿中,相邻块的预测值可能来自不同图像的不同位置,导致预测残差信号在块边界产生数值不连续。

  • 使用原因

环路滤波处理后的重建像素更有利于参考,进一步减小后续编码像素的预测残差,有效地提高了视频的主客观质量。 详细需要自己在详细阅读,这里不展开解释了。

熵编码

当帧间压缩去掉了时间的冗余、视觉冗余(I-PCM模式),帧内压缩去掉了空间的冗余、视觉上冗余之后,得到的残差数据,这时候4x4的像素块经过变换和量化之后,低频信号集中在左上角,大量高频信号集中在右下角。

左边的低频信号相对数值较大,而右下角的大量高频信号都被量化成0、1和-1;变换量化后的残差信息有一定的统计特性和规律。

熵编码压缩是一种无损压缩,其实现原理是使用新的编码来表示输入的数据,从而达到压缩的效果。常用的熵编码有游程编码,哈夫曼编码和CAVLC编码等。

CAVLC 『Context-Based Adaptive Variable Length Coding』可变字长编码

详情的话需要google一下。编码过程包括:

A、非零系数数目(TotalCoeffs)和拖尾系数数目(TrailingOnes)的编码 B、每一个拖尾系数的符号正负性编码(按照Z扫面结果的逆序编码) C、除拖尾系数外的每一个非零系数幅值(Level,包含正负号信息)编码(按照Z扫描结果的逆序编码)

结尾

其实整个流程是可以简化成

1)对空域和时域的冗余进行建模(帧内预测和帧间预测) 2)对应的模型 转化为 句法元素 3)句法元素--> 二进制流 4)二进制-->熵编码 5)最后得出码流。

参考文章:

https://www.cnblogs.com/Lxk0825/p/9925064.html

https://www.cnblogs.com/my_life/articles/6265265.html

https://www.jianshu.com/p/06a28206d8dc

https://zhuanlan.zhihu.com/p/98378872

https://www.jianshu.com/p/8edb448cf22e

https://cloud.tencent.com/developer/article/1493226

文章分享自微信公众号:
字节流动

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!

作者:KoonChaoSo
原始发表时间:2021-12-13
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • 音视频技术基础(一)--音视频技术概念基础

    各位大佬好,我是一个刚入坑的小菜鸡,黑眼圈云豆。最近开始学习TRTC实时音视频技术,我会记录并分享我的一些学习心得和体会,欢迎各位大佬来一起交流指正。

    黑眼圈云豆
  • 「音视频专题」 音视频基础概念介绍

    大家好,从本文开始我们将从 Android 音视频专题开始探索,并按照 iOS/Android 音视频开发专题介绍 依次开始。iOS 音视频专题将在 Andro...

    100001509164
  • 音视频录制基础原理概念

    初次接触音视频领域时的小伙伴,可能大多数都像我一样并不太了解整体的流程。音视频领域细分的话,还可以分出很多分支,例如:嵌入式设备中的运用(例如设备有摄像头和麦克...

    TrueDei
  • 音视频基础概念合集:148 个问题带你快速上车音视频丨音视频基础

    音视频是一个有一定技术门槛的垂直领域,对于前端、iOS/Android 客户端、服务端开发同学来说,这都是一个不错的职业发展方向。对于刚开始接触音视频开发的同学...

    关键帧
  • 音视频开发基础知识(1)——图像基本概念

    **像素是图像的基本单元,一个个像素就组成了图像。你可以认为像素就是图像中的一个点。**在下面这张图中,你可以看到一个个方块,这些方块就是像素。

    老马的编程之旅
  • 【Android 直播软件开发:音视频硬解码篇】

    时至今日,短视频App可谓是如日中天,一片兴兴向荣。随着短视频的兴起,音视频开发也越来越受到重视,但是由于音视频开发涉及知识面比较广,入门门槛相对较高,让许许多...

    云豹kj的晨曦
  • 音视频开发入门_视频制作基础知识

    音视频涉及语音信号处理、数字图像处理、信息论、封装格式、编解码、流媒体协议、网络传输、渲染、算法等。在现实生活中,音视频扮演着越来越重要的角色,比如视频会议、...

    全栈程序员站长
  • 【Android 音视频开发打怪升级:音视频硬解码篇】一、音视频基础知识

    不知道大家小时候是否玩过一种动画小人书,连续翻动的时候,小人书的画面就会变成一个动画,类似现在的gif格式图片。

    开发的猫
  • 《音视频开发进阶指南》—— 读书笔记

    前言 之前偶然看到一个PPT,是一些视频特效的讲解。首页如下: ? PPT解析了模糊镜像、电击效果、灵魂出窍、动态晕影等视频处理效果,最后推荐作者自己写的书: ...

    落影
  • 音视频必知会(一)

    随着通信技术的不断发展,互联网信息的传播与娱乐方式经历了从文字到图片再到音视频的转变,音视频通信,直播互动,短视频等应用百花齐放,特别是5G时代的到来,互联网对...

    PengJie
  • 零基础入门:实时音视频技术基础知识全面盘点

    随着移动网络速度越来越快、质量越来越来,实时音视频技术已经在各种应用场景下全面开花,语音通话、视频通话、视频会议、远程白板、远程监控等等。

    JackJiang
  • 实时音视频面视必备:快速掌握11个视频技术相关的基础概念

    随着移动互联网的普及,实时音视频技术已经在越来越多的场景下发挥重要作用,已经不再局限于IM中的实时视频聊天、实时视频会议这种功能,在远程医疗、远程教育、智能家居...

    JackJiang
  • 微信团队分享:微信Android版小视频编码填过的那些坑

    Android端的视频相关的开发,大概一直是整个Android生态,以及Android API中,最为分裂以及兼容性问题最为突出的一部分。摄像头,以及视频编码相...

    JackJiang
  • WebRTC Insertable Stream 初探与 WebRTC"管道化"

    在"WebRTC的现状与未来"(https://webrtchacks.com/webrtc-today-tomorrow-bernard-aboba-qa/)...

    刘连响

扫码关注腾讯云开发者

领取腾讯云代金券