1

我正在尝试使用 libav 将 RGB 图像数据的向量(源自 .png 图像)转换为 YUV420p 格式。

在 libav 示例代码中,以下内容用于创建虚拟图像:

/* prepare a dummy image */
static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
{
    int x, y, i;

    i = frame_index;

    /* Y */
    for(y=0;y<height;y++) {
        for(x=0;x<width;x++) {
            pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
        }
    }

    /* Cb and Cr */
    for(y=0;y<height/2;y++) {
        for(x=0;x<width/2;x++) {
            pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
            pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
        }
    }
}

我不清楚这里的一些事情:

首先,我是否需要重新排列输入向量中的 RGB 数据,使其适合编码为 YUV420p?

其次,我知道每个像素都有一个 Y 值,而 Cb 和 Cr 值用于四个 (2x2) 像素。我不明白的是 RGB 数据是如何“减少”到 Cb 和 Cr 值的——有没有一个例子说明如何在任何地方做到这一点?

4

1 回答 1

0

我不完全确定你想要达到什么目标,所以我会尽我所能直接回答你的问题(请随时跟进澄清评论):

1) 您将 RGB 数据转换为 YUV,这将涉及一些重新排列。打包的 RGB 数据在哪里都很好。你真的不需要调整它。实际上,出于缓存位置的原因,最好将其打包。

2) 如您所知,YUV 4:2:0 为每个像素编码一个 Y 样本,但每个 2x2 块共享一个 Cb 和一个 Cr 值。但是,也有 YUV 4:4:4 的数据。这是每个像素都有自己的 Y、Cb 和 Cr 样本的地方。转换 RGB -> YUV 4:2:0 的简单策略是转换 RGB -> YUV 4:4:4,然后平均(算术平均值)每个 2x2 Cb 样本块。还有其他算法(例如涉及更多周围样本的过滤器),但是如果您只是在试验这些东西的工作原理,这应该可以工作。

实验(和速度)的另一个策略是只计算 Y 平面并将 Cb 和 Cr 平面保持在 128 不变。这将产生灰度图像。

对于实际工作,您可能希望利用 libav 提供的内置转换工具。

于 2013-02-13T07:23:53.540 回答