视频编解码 |
您所在的位置:网站首页 › 视频编码器有什么用 › 视频编解码 |
目录
视频编码器基础认知什么是视频编解码器为什么需要视屏编解码器视频编码器与数字视频容器视频编码标准的历史
通用编解码器1、图片分区查看分区
2、预测3、转换使用全部像素形成每个系数
4、量化5、熵编码VLC编码算术编码
6、比特流格式H.264 比特流检查H.264比特流
总结
视频编码器基础认知
什么是视频编解码器
简单来说就是用于压缩或解压数字视频的软件或硬件 编码是信息从一种形式或格式转换为另一种形式的过程,解码是编码的反向。 适用于视频 编码是将视频、音频的原始格式的文件通过压缩技术转换成另一种格式(视频如h.264,h.265,m-jpeg等)。解码是编码的反向过程。应用中,一般是将h.264,h.265格式数据解码成如YUV格式裸流交给显示器显示。 为什么需要视屏编解码器需要在有限的带宽或存储空间下提升视频的质量。 简单计算一下,30帧,每像素24bit,分辨率480x240的视频,需要的带宽约为82.944Mbps。电视或互联网提供 HD/FullHD/4K 只能靠视频编解码器 视频编码器与数字视频容器初学者一个常见的错误是混淆数字视频编解码器和数字视频容器。 我们可以将容器视为包含视频(也很可能包含音频)元数据的包装格式,压缩过的视频可以看成是它承载的内容。 容器格式也被称为封装格式允许将多个数据流嵌入到单个文件中。 例如:可以放很多.txt的压缩包ZIP格式,和多媒体的播放格式如MP4和AVI。 通常,视频文件的格式定义其视频容器。例如,文件 video.mp4 可能是 MPEG-4 Part 14 容器,一个叫 video.mkv 的文件可能是 matroska。我们可以使用 ffmpeg 或 mediainfo 来完全确定编解码器和容器格式。 视频编码标准的历史在我们跳进通用编解码器内部工作之前,让我们回头了解一些旧的视频编解码器。 视频编解码器 H.261 诞生在 1990(技术上是 1988),被设计为以 64 kbit/s 的数据速率工作。它已经使用如色度子采样、宏块,等等理念。在 1995 年,H.263 视频编解码器标准被发布,并继续延续到 2001 年。 在 2003 年 H.264/AVC 的第一版被完成。在同一年,一家叫做 TrueMotion 的公司发布了他们的免版税有损视频压缩的视频编解码器,称为 VP3。在 2008 年,Google 收购了这家公司,在同一年发布 VP8。在 2012 年 12 月,Google 发布了 VP9,市面上大约有 3/4 的浏览器(包括手机)支持。 AV1 是由 Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel, Cisco 等公司组成的开放媒体联盟(AOMedia)设计的一种新的视频编解码器,免版税,开源。第一版 0.1.0 参考编解码器发布于 2016 年 4 月 7 号。 我们接下来要介绍通用视频编解码器背后的主要机制,大多数概念都很实用,并被现代编解码器如 VP9, AV1 和 HEVC 使用。 需要注意:我们将简化许多内容。有时我们会使用真实的例子(主要是 H.264)来演示技术。 1、图片分区第一步是将帧分成几个分区,子分区甚至更多。 通常,编解码器将这些分区组织成切片(slices )或条带(tiles),宏(或编码树单元)和许多子分区。 这些分区的最大大小有所不同,HEVC 设置成 64x64,而 AVC 使用 16x16,但子分区可以达到 4x4 的大小。 回顾帧的分类。你也可以把这些概念应用到块,因此我们可以有 I 切片,B 切片,I 宏块等等。 查看分区我们也可以使用 Intel® Video Pro Analyzer(需要付费,但也有只能查看前 10 帧的免费试用版)。 一旦我们有了分区,就可以在它们之上做出预测。 视频编解码——消除视频冗余的方法及原理 对于帧间预测,我们需要发送运动向量和残差对于帧内预测,我们需要发送预测方向和残差 3、转换在我们得到残差块(预测分区-真实分区)之后,我们可以用一种方式变换它,这样我们就知道哪些像素我们应该丢弃,还依然能保持整体质量。这个确切的行为有几种变换方式。 尽管有其它的变换方式,但我们重点关注离散余弦变换(DCT)。DCT 的主要功能有: 将像素块转换为相同大小的频率系数块。压缩能量,更容易消除空间冗余。可逆的,也意味着你可以还原回像素。2017 年 2 月 2 号,F. M. Bayer 和 R. J. Cintra 发表了他们的论文:图像压缩的 DCT 类变换只需要 14 个加法。 如果你不理解每个要点的好处,不用担心,我们会尝试进行一些实验,以便从中看到真正的价值。 我们来看下面的像素块(8x8): 这个系数块有一个有趣的属性:高频部分和低频部分是分离的。
频率是指信号变化的速度。 让我们通过实验学习这点,我们将使用 DCT 把原始图像转换为频率(系数块),然后丢掉最不重要的系数。 首先,我们将它转换为其频域。 重要的是要注意,每个系数并不直接映射到单个像素,但它是所有像素的加权和。这个神奇的图形展示了如何计算出第一和第二个系数,使用每个唯一的索引做权重。 当我们丢弃一些系数时,在最后一步(变换),我们做了一些形式的量化。这一步,我们选择性地剔除信息(有损部分)或者简单来说,我们将量化系数以实现压缩。 我们如何量化一个系数块?一个简单的方法是均匀量化,我们取一个块并将其除以单个的值(10),并舍入值。 这不是最好的方法,因为它没有考虑到每个系数的重要性,我们可以使用一个量化矩阵来代替单个值,这个矩阵可以利用 DCT 的属性,多量化右下部,而少(量化)左上部,JPEG 使用了类似的方法,你可以通过查看源码看看这个矩阵。 5、熵编码在我们量化数据(图像块/切片/帧)之后,我们仍然可以以无损的方式来压缩它。有许多方法(算法)可用来压缩数据。我们将简单体验其中几个,你可以阅读这本很棒的书去深入理解:Understanding Compression: Data Compression for Modern Developers。 VLC编码让我们假设我们有一个符号流:a, e, r 和 t,它们的概率(从0到1)由下表所示 aert概率0.30.30.20.2我们可以分配不同的二进制码,(最好是)小的码给最可能(出现的字符),大些的码给最少可能(出现的字符)。 aert概率0.30.30.20.2二进制码0101101110让我们压缩 eat 流,假设我们为每个字符花费 8 bit,在没有做任何压缩时我们将花费 24 bit。但是在这种情况下,我们使用各自的代码来替换每个字符,我们就能节省空间。 第一步是编码字符 e 为 10,第二个字符是 a,追加(不是数学加法)后是 [10][0],最后是第三个字符 t,最终组成已压缩的比特流 [10][0][1110] 或 1001110,这只需 7 bit(比原来的空间少 3.4 倍)。 请注意每个代码必须是唯一的前缀码,Huffman 能帮你找到这些数字。虽然它有一些问题,但是视频编解码器仍然提供该方法,它也是很多应用程序的压缩算法。 编码器和解码器都必须知道这个(包含编码的)字符表,因此,你也需要传送这个表。 算术编码让我们假设我们有一个符号流:a, e, r, s 和 t,它们的概率由下表所示。 aerst概率0.30.30.150.050.2考虑到这个表,我们可以构建一个区间,区间包含了所有可能的字符,字符按出现概率排序。 在第一个区间,我们发现数字落入了一个子区间,因此,这个子区间是我们的第一个字符,现在我们再次切分这个子区间,像之前一样做同样的过程。我们会注意到 0.36 落入了 a 的区间,然后我们重复这一过程直到得到最后一个字符 t(形成我们原始编码过的流 eat)。 编码器和解码器都必须知道字符概率表,因此,你也需要传送这个表。 非常巧妙,不是吗?人们能想出这样的解决方案实在是太聪明了,一些视频编解码器使用这项技术(或至少提供这一选择)。 关于无损压缩量化比特流的办法,这篇文章无疑缺少了很多细节、原因、权衡等等。作为一个开发者你应该学习更多。刚入门视频编码的人可以尝试使用不同的熵编码算法,如ANS。 6、比特流格式完成所有这些步之后,我们需要将压缩过的帧和内容打包进去。需要明确告知解码器编码定义,如颜色深度,颜色空间,分辨率,预测信息(运动向量,帧内预测方向),配置*,层级*,帧率,帧类型,帧号等等更多信息。 * 译注:原文为 profile 和 level,没有通用的译名 接下来简单地学习 H.264 比特流。第一步是生成一个小的 H.264* 比特流,可以用 ffmpeg 来做。 ./s/ffmpeg -i /files/i/minimal.png -pix_fmt yuv420p /files/v/minimal_yuv420.h264* ffmpeg 默认将所有参数添加为 SEI NAL 这个命令会使用下面的图片作为帧,生成一个具有单个帧,64x64 和颜色空间为 yuv420 的原始 h264 比特流。 AVC (H.264) 标准规定信息将在宏帧(网络概念上的)内传输,称为 NAL(网络抽象层)。NAL 的主要目标是提供“网络友好”的视频呈现方式,该标准必须适用于电视(基于流),互联网(基于数据包)等。
通常,比特流的第一个 NAL 是 SPS,这个类型的 NAL 负责传达通用编码参数,如配置,层级,分辨率等。 如果我们跳过第一个同步标记,就可以通过解码第一个字节来了解第一个 NAL 的类型。 例如同步标记之后的第一个字节是 01100111,第一位(0)是 forbidden_zero_bit 字段,接下来的两位(11)告诉我们是 nal_ref_idc 字段,其表示该 NAL 是否是参考字段,其余 5 位(00111)告诉我们是 nal_unit_type 字段,在这个例子里是 NAL 单元 SPS (7)。 SPS NAL 的第 2 位 (binary=01100100, hex=0x64, dec=100) 是 profile_idc 字段,显示编码器使用的配置,在这个例子里,我们使用受限高配置,一种没有 B(双向预测) 切片支持的高配置。
ue(v): 无符号整形 Exp-Golomb-coded 如果我们对这些字段的值进行一些计算,将最终得出分辨率。我们可以使用值为 119( (119 + 1) * macroblock_size = 120 * 16 = 1920)的 pic_width_in_mbs_minus_1 表示 1920 x 1080,再次为了减少空间,我们使用 119 来代替编码 1920。 如果我们再次使用二进制视图检查我们创建的视频 (ex: xxd -b -c 11 v/minimal_yuv420.h264),可以跳到帧自身上一个 NAL。
为了获得一些字段(ue(v), me(v), se(v) 或 te(v))的值,我们需要称为 Exponential-Golomb 的特定解码器来解码它。当存在很多默认值时,这个方法编码变量值特别高效。 这个视频里 slice_type 和 frame_num 的值是 7(I 切片)和 0(第一帧) 我们可以将比特流视为一个协议,如果你想学习更多关于比特流的内容,请参考 ITU H.264 规范。这个宏观图展示了图片数据(压缩过的 YUV)所在的位置。 我们可以生成一个单帧视频,使用 mediainfo 检查它的 H.264 比特流。事实上,你甚至可以查看解析 h264(AVC) 视频流的源代码。
我们可以看到我们学了许多使用相同模型的现代编解码器。事实上,让我们看看 Thor 视频编解码器框图,它包含所有我们学过的步骤。你现在应该能更好地理解数字视频领域内的创新和论文。 使用的视频是每像素使用 0.031 bit。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |