YUV420p 到 RGB 的转换改变了 U 和 V 值 - iOS Unity3D

YUV420p to RGB conversion has shifted U and V values - iOS Unity3D

我在 Unity 中有一个原生插件,可以使用 FFMPEG 将 H264 帧解码为 YUV420p。

为了显示输出图像,我将 YUV 值重新排列为 RGBA 纹理并使用 Unity 着色器将 YUV 转换为 RGB(只是为了使其更快)。

以下是我原生插件中的重排代码:

unsigned char* yStartLocation = (unsigned char*)m_pFrame->data[0];
unsigned char* uStartLocation = (unsigned char*)m_pFrame->data[1];
unsigned char* vStartLocation = (unsigned char*)m_pFrame->data[2];

for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {

        unsigned char* y = yStartLocation + ((y * width) + x);
        unsigned char* u = uStartLocation + ((y * (width / 4)) + (x / 2));
        unsigned char* v = vStartLocation + ((y * (width / 4)) + (x / 2));
        //REF: https://en.wikipedia.org/wiki/YUV

        // Write the texture pixel
        dst[0] = y[0]; //R
        dst[1] = u[0]; //G
        dst[2] = v[0]; //B
        dst[3] = 255;  //A

        // To next pixel
        dst += 4;

        // dst is the pointer to target texture RGBA data
    }
}

将 YUV 转换为 RGB 的着色器工作完美,我已经在多个项目中使用它。

现在,我在 iOS 平台上使用相同的代码进行解码。但出于某种原因,U 和 V 值现在发生了变化:

Y 纹理

U 纹理

iOS 或 OpenGL 有什么我遗漏的吗?

非常感谢任何帮助。 谢谢!

请注意,我在第一个屏幕截图中填写了 R=G=B = Y,在第二个屏幕截图中填写了 U。(如果有意义的话)

编辑: 这是我得到的输出:

编辑2: 根据一些研究,我认为这可能与隔行扫描有关。

参考:Link

现在我已经转向使用 sws_scale 基于 CPU 的 YUV-RGB 转换并且它工作正常。

问题出在这一行:

uStartLocation + ((y * (width / 4)) + (x / 2));

应该是

uStartLocation + (((y / 2) * (width / 2)) + (x / 2));

因为 int 舍入导致整个帧移动。尝试优化计算时出现非常愚蠢的错误。

希望对大家有所帮助。