1. 前言

本文分析了 H.264 视频编码器的原理,对当今流行的 H.264编码器进行了比较,以 X264 开源编码器为例进行了源码级的分析,详细介绍了 X264 中的主要数据结构和函数调用关系。本文的分析能使用户对 H.264 视频编码原理有更深入的认识,并为自己的应用设计独特的视频编码器,提高视频编码性能。

2. H.264 编码器原理

2.1 H.264编码器的功能结构

如下图所示,H.264 标准压缩系统由视频编码层(Video Coding Layer,VCL)和网络提取层(Network Abstraction Layer,NAL)两部分组成。VCL 层主要包括帧内预测,帧间预测、变换量化、熵编码等压缩单元。NAL 层则用于为 VCL 层提供一个与网络无关的统一接口,它负责对视频数据进行封装打包后使其在网络中传送,它采用统一的数据格式,包括单个字节的包头信息、多个字节的视频数据与组帧、逻辑信道信令、定时信息、序列结束信号等。包头中包含存储标志和类型标志。存储标志用于指示当前数据不属于被参考的帧。类型标志用于指示图像数据的类型。VCL 可以传输按当前的网络情况调整的编码参数。

2.2 H.264 编码器工作流程

如下图所示,编码器采用的是变换和预测的混合编码法。输入的帧或场 Fn 以宏块为单位被编码器处理。首先,按帧内或帧间预测编码的方法进行处理。若采用帧内预测编码,其预测值 PRED 是由当前片中当前块的左侧和上侧已编码的象素点推出的,而如果采用帧间预测编码,其预测值 PRED 是由已编码的视频帧/场通过运动补偿得到的。预测值 PRED 和当前块相减后,产生一个残差块 Dn,经变换,量化后产生的变化系数 X 再经熵编码,与解码需要信息一起组成一个压缩码流, 经NAL 供传输和存储用。 为进一步提供预测用的参考图像,编码器还需要有重建图像的功能。 即将残差图像经反量化, 反变换后得到 Dn′与预测值PRED相加,得到 uFn′,经过滤波后得到 Fn′即为重建图像,可用于参考图像。

3. X264 开源编码器分析

3.1 三大开源编码器

目前 H.264的开源编码器主要有三类:JM,T264和 X264。JM 作为 H.264 的官方测试源码,由德国 hhi 研究所负责开发。它实现了 264 所有的特性,但其程序结构冗长,只考虑引入各种新特性以提高编码性能,忽视了编码复杂度,其编码复杂度极高,不宜实用。T264是中国视频编码自由组织联合开发的H.264编解码器, 编码器能编码输出标准的H.264码流,但解码器只能解 T264 编码器生成的码流,目前已经停止更新。X264 是网上自由组织联合开发的兼容 264 标准码流的编码器,它注重实用,和 JM 相比,在不明显降低编码性能的前提下,努力降低编码的计算复杂度,编码效率很高。

3.2 X264流程

因为 X264 编码器的高效率和高性能,应用之中较多使用,下面对 X264 进行源码分析,进一步分析 H.264 的编码器原理。

在 X264 编码器的调度中最重要的是 Encode 函数,是对整个视频序列的 H.264 编码。在函数中,首先进行了函数的初始化操作,然后判断是否已经编码完毕,如果没有则继续读取一帧数据到缓冲区,然后进行帧解码;如果编码完毕则退出编码流程。详细函数关系如下图所示:

其中,x264_encoder_open()这个函数是对不正确的参数进行修改,并对各结构体参数和cabac 编码,预测等需要的参数进行初始化。x264_picture_alloc()这个函数分配能容纳一帧sizeof(x264_picture_t)字节数的空间,然后进行初始化。p_read_frame()这个函数就是一次读入一帧到刚分配的空间,这里的数据都是原始的视频图像数据。Encode_frame()这个函数对视频序列其中一帧进行 264 编码。x264_picture_clean()和 x264_encoder_close()两个函数主要是编码后的处理工作,如将帧数据全置零等。

在 Encode_frame() 函数中开始上文提到的 VCL 编码和 NAL 编码,其中x264_encoder_encode()函数为 VCL 层编码, 其详细流程如下图所示。 其中, Setup new frame from picture 主要是将图片的原始数据赋值给一个未使用的帧,用于编码。Get frame to be encoded 主要是帧管理的操作,从编码帧的缓存中取出一帧来对他进行编码。Setup frame context 主要是对即将编码帧进行帧类型的预设定。 Init ,Write the bitstream主要是对参考列表的初始化,片头的初始化,以及对将编码后数据写入比特流进行传输。Update encoder state这部分是一帧编码后的编码器的更新处理部分,主要有参考帧的管理,去块滤波,象素内插等工作。Compute/Print statistics这部分并不属于编码的工作,只是对其中编码性能的统计计算和显示工作。

x264_slice_write()函数是编码中最重要的函数,以上所介绍的预测编码等都在这个函数中实现的。Init()函数主要是初始化的一些操作。x264_macroblock_cache_load()函数主要是把当前宏块的 up 宏块和 left 宏块的预测模式,非零系数值等数据加载进来,放到一个数组里面,供当前模块参考使用。 x264_macroblock_analyse()函数主要是模式选择的问题,通过对SAD 值或者其他 COST 值的分析,确定当前宏块的编码类型。以 I 帧模块为例,我们可以将它分割成16个4*4的块,如果这16个块的sad加起来小于按16*16的方式计算出来的sad值,我们就将这个 16*16 的块分成 16 个 4*4 的块进行编码,否则采用 16*16 的方式编码。x264_macroblock_encode()函数即是依据上面所确定的编码模式对当前宏块进行 264 编码。CABAC/CAVLC 部分为熵编码部分。

3.3 预测编码算法

帧内预测编码的预测值 P 是在一定的预测模式下,通过邻近已编码的象素值推出的。H.264 中的帧内预测分为 4×4 子块和 16×16 子块以及对 8x8 子块的预测模式。在 x264 代码中,帧内预测模式的算法主要在 predict.c 中。其中亮度象素有三种方式:16x16 宏块预测模式,8x8 子块预测模式,4x4 子块预测模式;色度象素有只有 8x8 色度预测模式。 帧间预测编码主要包括运动估计,运动补偿等,其中运动估计尤为重要。在 x264 中帧间运动估计有三种算法可供选择 X264_ME_DIA,X264_ME_HEX,X264_ME_ESA。

X264_ME_ESA::全搜索法,也称为穷尽搜索法,是对搜索范围内所有可能的候选位置计算 SAD(i,j)值,从中找出最小 SAD(绝对差值和),其对应偏移量即为所求运动矢量。此算法虽计算量大,但最简单、可靠,找到的必为全局最优点。

X264_ME_DIA::菱形搜索,搜索模板的形状和大小不但影响整个算法的运行速度,而且也影响它的性能。块匹配的误差实际上是在搜索范围内建立了误差表面函数,全局最小点即对应着最佳运动矢量。基于这两点事实,菱形算法采用了两种搜索模板,分别是有 9个检测点的大模板 LDSP(Large Diamond Search Pattern)和有 5 个检测点的小模板SDSP(SmallDiamond Search Pattern),搜索时先用大模板计算,当最小块误差 MBD点出现在中心点处时,将大模板 LDSP 换为 SDSP,再进行匹配计算,这时 5 个点中的 MBD 即为最优匹配点。

X264_ME_HEX::六边形搜索,与菱形搜索相似,只是搜索形状为六边形。

H264和x264简单介绍相关推荐

  1. x264参数介绍(帧类型和码率控制,分析和视频可用性信息)

    鉴于x264的参数众多,各种参数的配合复杂,为了使用者方便,x264建议如无特别需要可使用preset和tune设置.这套开发者推荐的参数较为合理,可在此基础上在调整一些具体参数以符合自己需要,手动设 ...

  2. H264和X264究竟有什么区别?

    先简单说一下,mkv和avi的格式只是封装容器,里面封装的是视频流+音频流.容器不会影响画面质量,影响质量的是容器里面封装的什么东西.所以你换换容器,而里面的东西不换的话,对清晰度字幕音频等是没有影响 ...

  3. 遗传算法的简单介绍以及模式定理的简单证明

    遗传算法   遗传算法(Genetic Algorithm,GA),最早是由美国的John holland在20世纪70年代提出.算法通过模拟达尔文生物进化论的自然选择以及遗传学机理的生物进化过程来搜 ...

  4. 2021年大数据ELK(十八):Beats 简单介绍和FileBeat工作原理

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 Beats 简单介绍和FileBeat工作原理 一.Beats 二.FileB ...

  5. 2021年大数据ELK(十五):Elasticsearch SQL简单介绍

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 Elasticsearch SQL简单介绍 一.SQL与Elasticsear ...

  6. 2021年大数据ELK(二):Elasticsearch简单介绍

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 一.Elasticsearch简介 1.介绍 2.创始人 二.E ...

  7. iOS开发UI篇—多控制器和导航控制器简单介绍

    iOS开发UI篇-多控制器和导航控制器简单介绍 一.多控制器 一个iOS的app很少只由一个控制器组成,除非这个app极其简单.当app中有多个控制器的时候,我们就需要对这些控制器进行管理 有多个vi ...

  8. 简单介绍一下R中的几种统计分布及常用模型

    统计学上分布有很多,在R中基本都有描述.因能力有限,我们就挑选几个常用的.比较重要的简单介绍一下每种分布的定义,公式,以及在R中的展示. 统计分布每一种分布有四个函数:d――density(密度函数) ...

  9. LVS(Linux Virtual Server)三种负载均衡模型和十种调度的简单介绍

    LVS(Linux Virtual Server)三种负载均衡模型和十种调度的简单介绍 LVS (Linux Virtual Server) LVS(Linux Virtual Server)其实就是 ...

最新文章

  1. C#中获取程序当前路径的集中方法
  2. [转]你在修佛,还是在修魔
  3. Uva592 Island of Logic
  4. zend studio 函数不提醒 小黄图标 小黄标
  5. SQL(Oracle)日常使用与不常使用函数的汇总
  6. 强制进程结束(内核函数)
  7. php7 验证url格式,url的组成格式为
  8. 公司没有与员工签订劳动合同,也没有给员工购买社保,现在员工被公司解雇,该如何要求赔偿?
  9. Linux mysql 主从复制
  10. 图像分割标注数据labelme解析时报错【Python已停止工作Windows正在检查该问题的解决方案...】【ValueError: Too many dimensions: 3 > 2】
  11. VS2005的DEBUG设置
  12. List集合对象去重及按属性去重的8种方法
  13. K均值算法(K-means)聚类
  14. 多种方法对网页文字进行快速复制(仅供学习使用,勿践踏他人成果)
  15. 扫码枪收银有手续费吗_为何超市“扫码枪”不输密码就可以付款?听收银员说完,不纠结了...
  16. 【网页前端】HTML基本语法之排版标签和表单标签
  17. 项目中生成requests.txt文件(virtualenv与pipreqs)
  18. 43套高质量PPT模板—创意风格主题
  19. 名帖337 张旭 草书《古诗四帖》
  20. uniapp开发小程序使用腾讯云IM(初始化配置,登录,监听,加群)

热门文章

  1. IDEA新建项目系列(8)——IDEA创建SSH项目
  2. Swagger2简单使用教程
  3. CAN总线基础知识(2)——CAN的数据帧
  4. SQL(结构化查询语言)的6个组成部分
  5. 【台式机DIY】我的第一台台式机电脑配置清单
  6. TaoCode-淘宝的SVN开源托管平台
  7. 李开复: 算法的力量
  8. matlab二维图形函数,在MATLAB中,画二维图形的常用函数为( )。
  9. COPY failed: file not found in build context or excluded by .dockerignore
  10. php 位运算符的实际应用(权限判断)