libaom 源码分析:AV1 帧内预测模式 Paeth 模式

发布于:2024-11-03 ⋅ 阅读:(9) ⋅ 点赞:(0)

Peath模式原理

  1. Paeth预测模式:AV1引入的新的帧内预测模式,由计算机科学家Alan W. Paeth在开发PNG格式时提出,因此以他的名字进行命名该模式;
  2. 原理:是一种加权预测,如图所示,根据其顶部(T)、左侧(L)和左上角(TL)的参考样本预测每个样本。在这些参考样本中,与(T + L – TL)的值最接近的那个值被选为预测样本。
    在这里插入图片描述
  3. 应用:Paeth预测模式特别适合于图像的平滑区域,因为它可以有效地减少预测误差,提高压缩效率。在AV1中,这种模式是多种帧内预测模式之一,与其他模式一起使用,以适应不同类型的图像内容。

libaom相关源码分析

  1. libaom 模式序号为 12,在 enums.h 中定义。
    在这里插入图片描述

  2. libaom 源码相关函数关系:
    在这里插入图片描述

  3. paeth_predictor函数

  • 外层循环遍历块的高度bh。
  • 内层循环遍历块的宽度bw。
  • paeth_predictor_single函数被调用来计算每个像素的预测值,该函数接受三个参数:左侧像素值left[r],上方像素值above[c],以及左上角像素值ytop_left。
  • 计算得到的预测值被存储在dst[c]中。
  • 每次内层循环结束后,dst指针增加stride,以移动到下一行的目标缓冲区。
static INLINE void paeth_predictor(uint8_t *dst, ptrdiff_t stride, int bw,
                                   int bh, const uint8_t *above,
                                   const uint8_t *left) {
  int r, c;
  const uint8_t ytop_left = above[-1];

  for (r = 0; r < bh; r++) {
    for (c = 0; c < bw; c++)
      dst[c] = (uint8_t)paeth_predictor_single(left[r], above[c], ytop_left);
    dst += stride;
  }
}
  1. paeth_predictor_single函数
  • 计算基础值(base):
    • base 是通过将顶部像素值 top 和左侧像素值 left 相加,然后减去左上角像素值 top_left 来计算的。这个基础值用于后续的差值计算。
  • 计算绝对差值:
    • p_left 是 base 和 left 之间的绝对差值。
    • p_top 是 base 和 top 之间的绝对差值。
    • p_top_left 是 base 和 top_left 之间的绝对差值。
    • 这些差值用于确定哪个参考像素(left、top 或 top_left)最接近 base。
  • 选择最接近的像素值:
    • 函数使用三元运算符来确定哪个参考像素的差值最小,即最接近 base。
    • 如果 p_left 是三个差值中最小的,返回 left。
    • 如果 p_top 小于 p_top_left 且不大于 p_left,返回 top。
    • 否则,返回 top_left。
  • 返回预测值:
    • 函数返回最接近 base 的像素值,这个值被认为是当前像素的最佳预测。
static INLINE uint16_t paeth_predictor_single(uint16_t left, uint16_t top,
                                              uint16_t top_left) {
  const int base = top + left - top_left;
  const int p_left = abs_diff(base, left);
  const int p_top = abs_diff(base, top);
  const int p_top_left = abs_diff(base, top_left);

  // Return nearest to base of left, top and top_left.
  return (p_left <= p_top && p_left <= p_top_left) ? left
         : (p_top <= p_top_left)                   ? top
                                                   : top_left;
}
  1. abs_diff 函数
  • 用于计算两个整数 a 和 b 之间的绝对差值。这个函数的实现非常简单且高效,它通过一个条件表达式(三元运算符)来确定 a 和 b 中哪个更大,并返回两者之间的差值。
static INLINE int abs_diff(int a, int b) { return (a > b) ? a - b : b - a; }