strided memcpy(3) 在 libvpx 中如何工作

问题描述 投票:0回答:2

我试图理解 libvpx 中的以下函数(

vp8/common/reconinter.c
):

void vp8_copy_mem16x16_c(unsigned char *src, int src_stride, unsigned char *dst,
                         int dst_stride) {
  int r;

  for (r = 0; r < 16; ++r) {
    memcpy(dst, src, 16);

    src += src_stride;
    dst += dst_stride;
  }
}

(8x8 和 8x4 版本也存在于同一源文件中。)

它将 16 个字节从

src
复制到
dst
16 次,但同时,它向
stride
src
添加自定义
dst
。如果没有计算机图形和 DSP 方面的先验知识,我对这些功能感到非常困惑:在
stride
src
中支持自定义
dst
有什么意义?使用此类函数而不是仅仅将整个 16 x 16 字节复制在一起有哪些示例或好处?

非常感谢!

更新:为了明确起见,当矢量优化版本在目标平台上不可用时,

vp8_copy_mem16x16_c
在构建阶段被重新定义为
vp8_copy_mem16x16

c memcpy codec stride libvpx
2个回答
1
投票

如果我理解正确的话,你的问题是步幅的用途是什么。

libvpx
的背景下,它有两个大的用例:

  • 对源流中的各个块进行编码。如果您有整个图像,则可以使用等于

    <image width + image stride - block width>
    的源步幅和 0 的目标步幅(或算法中所需的任何内容)来有效地提取块。编辑:要明确的是,大多数编码和解码视频操作都在正方形或矩形块上进行。 JPEG 就是一个例子,但所有 mp4 和 VP8/9 操作也是基于块的。这是一个非常基本、非常常用的操作。

  • 虽然大多数 API 允许非二次幂图像、高效内存访问,尤其是在 GPU 上,但几乎需要它(或者至少需要一些对齐填充)。源和目的地都可以有不同的此类要求,并且两个跨步参数都在这里发挥作用。

然而,一般来说,步幅还有第三种用例:精灵块传输。与上面的第一点类似,您可以通过使用步幅复制内存来非常有效地将精灵传输到纹理(和/或屏幕,如果没有双缓冲)。


0
投票

这是试图在两个图像之间复制一个 16x16 的方块(即二维数组)。

预期用途是将

src
dst
设置为块的起始位置,并将
stride
设置为整个图像的宽度。

© www.soinside.com 2019 - 2024. All rights reserved.