代码以ffmpeg为例,h264解码代码在h264.c里。

环路滤波(Loop Filter)部分

FFmpeg的H.264解码器调用decode_slice()函数完成了解码工作。这些解码工作可以大体上分为3个步骤:熵解码,宏块解码以及环路滤波。

环路滤波主要用于滤除方块效应。decode_slice()在解码完一行宏块之后,会调用loop_filter()函数完成环路滤波功能。loop_filter()函数会遍历该行宏块中的每一个宏块,并且针对每一个宏块调用ff_h264_filter_mb_fast()。ff_h264_filter_mb_fast()又会调用h264_filter_mb_fast_internal()。
         h264_filter_mb_fast_internal() 完成了一个宏块的环路滤波工作。该函数调用filter_mb_edgev()和filter_mb_edgeh()对亮度垂直边界和水平边界进行滤波,或者调用filter_mb_edgecv()和filter_mb_edgech()对色度的的垂直边界和水平边界进行滤波。

decode_slice()

decode_slice()用于解码H.264的Slice。该函数完成了“熵解码”、“宏块解码”、“环路滤波”的功能。它的定义位于libavcodec\h264_slice.c。

decode_slice()的流程:

(1)判断H.264码流是CABAC编码还是CAVLC编码,进入不同的处理循环。
(2)如果是CABAC编码,首先调用ff_init_cabac_decoder()初始化CABAC解码器。然后进入一个循环,依次对每个宏块进行以下处理:

a)调用ff_h264_decode_mb_cabac()进行CABAC熵解码

b)调用ff_h264_hl_decode_mb()进行宏块解码

c)解码一行宏块之后调用loop_filter()进行环路滤波

d)此外还有可能调用er_add_slice()进行错误隐藏处理

(3)如果是CABAC编码,直接进入一个循环,依次对每个宏块进行以下处理:

a)调用ff_h264_decode_mb_cavlc()进行CAVLC熵解码

b)调用ff_h264_hl_decode_mb()进行宏块解码

c)解码一行宏块之后调用loop_filter()进行环路滤波

d)此外还有可能调用er_add_slice()进行错误隐藏处理

可以看出,环路滤波函数是loop_filter()。

loop_filter

loop_filter()循环遍历一行宏块,并且针对每一个宏块调用了ff_h264_filter_mb_fast()函数。ff_h264_filter_mb_fast()用于对一个宏块进行环路滤波工作。该函数的定义位于libavcodec\h264_loopfilter.c。ff_h264_filter_mb_fast()代码比较简单,其中调用了另一个函数h264_filter_mb_fast_internal()。

h264_filter_mb_fast_internal

h264_filter_mb_fast_internal()用于对一个宏块进行环路滤波。该函数的定义位于libavcodec\h264_loopfilter.c。通过源代码整理出来h264_filter_mb_fast_internal()的流程如下:
(1)读取QP等几个参数,用于推导滤波门限值alpha,beta。
(2)如果是帧内宏块(Intra),作如下处理:

a)对于水平的边界,调用filter_mb_edgeh()进行滤波。
b)对于垂直的边界,调用filter_mb_edgev()进行滤波。

帧内宏块滤波过程中,对于在宏块边界上的边界(最左边的垂直边界和最上边的水平边界),采用滤波强度Bs为4的滤波;对于其它边界则采用滤波强度Bs为3的滤波。

(3)如果是其他宏块,作如下处理:

a)对于水平的边界,调用filter_mb_edgeh()进行滤波。
b)对于垂直的边界,调用filter_mb_edgev()进行滤波。

此类宏块的滤波强度需要另作判断。

总体说来,一个宏块内部的滤波顺序如下图所示。图中的“0”、“1”、“2”、“3”为滤波的顺序。可以看出首先对垂直边界进行滤波,然后对水平边界进行滤波。垂直边界滤波按照从左到右的顺序进行,而水平边界的滤波按照从上到下的顺序进行。

filter_mb_edgeh()用于对水平边界进行滤波。该函数定义位于libavcodec\h264_loopfilter.c。该函数首先计算了alpha,beta两个滤波的门限值,然后根据输入信息判断是否需要强滤波。如果需要强滤波(Bs取值为4),就调用 H264DSPContext中的滤波汇编函数h264_v_loop_filter_luma_intra();如果不需要强滤波(Bs取值为1、2、 3),就调用H264DSPContext中的滤波汇编函数h264_v_loop_filter_luma()。
    在这里有一点需要注意,对水平边界进行滤波的函数(函数名中包含“_edgeh”),调用的是垂直滤波函数(函数名中包含“_v”)。

filter_mb_edgev()用于对垂直边界进行滤波。该函数定义位于libavcodec\h264_loopfilter.c,filter_mb_edgev()的定义与filter_mb_edgeh()是类似的。也是先计算了alpha,beta两个滤波的门限值,然后根据 输入信息判断是否需要强滤波。如果需要强滤波(Bs取值为4),就调用H264DSPContext中的滤波汇编函数 h264_h_loop_filter_luma_intra();如果不需要强滤波(Bs取值为1、2、3),就调用H264DSPContext中的 滤波汇编函数h264_h_loop_filter_luma()。下文将会对H264DSPContext中的 h264_h_loop_filter_luma()和h264_h_loop_filter_luma_intra()这两个汇编函数进行分析。

环路滤波小知识

H.264解码器在解码后的数据一般情况下会出现方块效应。产生这种效应的原因主要有两个:
(1)DCT变换后的量化造成误差(主要原因)。
(2)运动补偿
正是由于这种块效应的存在,才需要添加环路滤波器调整相邻的“块”边缘上的像素值以减轻这种视觉上的不连续感。下面一张图显示了环路滤波的效果。图中左边的图没有使用环路滤波,而右边的图使用了环路滤波。

环路滤波的门限

并不是所有的块的边界处都需要环路滤波。例如画面中物体的边界正好和块的边界重合的话,就不能进行滤波,否则会使画面中物体的边界变模糊。因此需要区别开物体边界和块效应边界。一般情况 下,物体边界两边的像素值差别很大,而块效应边界两边像素值差别比较小。《H.264标准》以这个特点定义了2个变量alpha和beta来判决边界是否 需要进行环路滤波。只有满足下面三个条件的时候才能进行环路滤波:

| p0 - q0 | < alpha

| p1 – p0 | < beta

| q1 - q0 | < beta

简 而言之,就是边界两边的两个点的像素值不能太大,即不能超过alpha;边界一边的前两个点之间的像素值也不能太大,即不能超过beta。其中alpha 和beta是根据量化参数QP推算出来(具体方法不再记录)。总体说来QP越大,alpha和beta的值也越大,也就越容易触发环路滤波。由于QP越大表明压缩的程度越大,所以也可以得知高压缩比的情况下更需要进行环路滤波。

环路滤波汇编函数的初始化函数ff_h264dsp_init()。f_h264dsp_init()用于初始化环路滤波函数(实际上该函数也用于初始化DCT反变换和Hadamard反变换函数)。该函数的定义位于libavcodec\h264dsp.c。ff_h264dsp_init()初始化了环路滤波函数,DCT反变换函数和Hadamard反变换函数。

h264_v_loop_filter_luma_8_c()实现了亮度边界垂直普通滤波器(处理水平边界)。该函数的定义位于libavcodec\h264dsp_template.c。

h264解码之环路滤波相关推荐

  1. FFmpeg的H.264解码器源代码简单分析:环路滤波(Loop Filter)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  2. AVS解码—环路滤波

    在解码框架中最后是做滤波处理 环路滤波是以微块做处理,按照解码顺序依次进行处理,在AVS中就是以16*16的大小 对亮度和色度分别做环路滤波,首先从左到右对垂直边界滤波,然后从上到下进行处理. 需要滤 ...

  3. 海思HI35xx平台软件开发快速入门之H264解码实例

    前言 H264视频编码技术诞生于2003年,至今已有十余载,技术相当成熟,它的优势在于有高的视频的压缩率,利用帧间和帧内预测(Estimation).变换(Transform)和反变换.量化(Quan ...

  4. HEVC算法和体系结构:环路滤波技术

    环路滤波(In-Loop Filtering)技术 类似于以往的视频编码标准,HEVC仍采用基于块的混合编码框架,一些失真效应仍然存在,如方块效应.振铃效应.颜色偏差以及图像模糊等等.为了解决这些问题 ...

  5. FFmpeg的HEVC解码器源代码简单分析:环路滤波(Loop Filter)

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  6. 视频千倍压缩背后的技术原理之环路滤波

    随着5G的成熟和广泛商用,带宽越来越高,让传输视频变得更加容易.移动设备算力的提升.存储容量的提升,也使得视频技术的应用越来越广泛.视频相关的技术,特别是视频压缩技术,因其专业性,深入开发的门槛较高, ...

  7. HEVC/H.265面试问题准备(PART 3. 环路滤波+熵编码)

    近期因为要准备暑期实习以及后期的秋招环节,再一次温习了<新一代高效视频编码H.265/HEVC原理.标准与实现>经典书籍,现在记录下有关阅读心得以及可能面试的问题(所有的答案都是我自己思考 ...

  8. VVC/VTM:环路滤波——Luma mapping with chroma scaling (LMCS)

    VTM中环路滤波的顺序:LMCS,deblocking filter,SAO 和ALF.其中deblocking filter和SAO 与HEVC中的相同. Luma mapping with chr ...

  9. VVC环路滤波(一):ALF

    在VTM5中提供了三种环路滤波技术:去方块滤波(Deblocking filter,DF),样点自适应补偿(Sample adaptive offset,SAO)和自适应环路滤波(adaptive l ...

最新文章

  1. Python爬虫破解有道翻译
  2. Zend Framework 2 中,定制error 的layout
  3. 皮一皮:男女的不同...
  4. 禁用浏览器滚动条的解决方案
  5. 什么是电源正激和反激? 正激和反激有什么区别特点?如何快速区分
  6. 【GPU编程】基于GPU的光线投射体绘制(GPU-Based Ray-Casting Volume Rendering)入门学习
  7. golang服务开发平滑升级之优雅重启
  8. 减速器的参数优化 毕业设计 matlab,matlab减速器计算机辅助设计系统+程序+CAD图纸+源程序...
  9. Win7下用的XP虚拟机
  10. 山东大学高频电子线路实验七 锁相环调频及解调实验详解
  11. 计算机网络原理 实验3《IP数据包捕获及数据分析》
  12. 母函数(指数型)(泰勒展开式)
  13. iview form表单验证手机号
  14. 知数堂MySQL DBA在线培训第八期招生中
  15. 肺管家科普:引发肺气肿的原因竟然是这些...
  16. spark-sql调优
  17. java 中的NIO
  18. macbook上好用的解压软件_好用的Mac解压软件推荐
  19. 什么是业务,什么是业务架构?
  20. 安卓银行木马新增“keylogger”功能,攻击能力倍增

热门文章

  1. 《操作系统——精髓与设计原理(第八版)》复习题抄录
  2. DDR,DDR2,DDR3,DDR4,LPDDR区别
  3. 1525D. Armchairs
  4. 姓莫的女孩子叫什么名字好听
  5. win8下去除QQ聊天窗口的广告
  6. PMP : PMP备考心得 (8)
  7. Py人工智能一般用什么框架?
  8. CSS3之多列布局columns学习
  9. 谈谈你对间隙锁的理解
  10. 怎么修改win8计算机用户名和密码忘了怎么办,win8忘记了登陆密码怎么办|win8用户登入密码忘了的解决措施...