从RGB帧创建webm视频

4

我有一个应用程序,可以生成一堆jpg文件,我需要将它们转换成webm视频。我正在尝试从JPEG文件中获取RGB数据并将其输入到vpxenc示例中。在输出视频中,我可以看到原始JPG图像的基本形状,但每个像素都呈绿色(即使应该是黑色的像素也是绿色的),而且每隔一行扫描线都有一些垃圾数据。

我正在尝试提供VPX_IMG_FMT_YV12数据,我假设它的结构如下:

对于每个帧        8位Y数据        每个2x2 V块的8位平均值        每个2x2 U块的8位平均值

这里有一个源图像和输出视频的屏幕截图:

Images

很可能我没有正确执行RGB->YV12转换,但即使我只编码8位Y数据并将U和V块设置为0,视频看起来也差不多。我基本上是通过以下方程式处理我的RGB数据:

// (R, G, and B are 0-255)
float y = 0.299f*R + 0.587f*G + 0.114f*B;
float v = (R-y)*0.713f;
float u = (B-v)*0.565f;

然后为了生成写入vpxenc的U和V的2x2过滤值,我只需要执行(a + b + c + d) / 4,其中a、b、c、d是每个2x2像素块的U或V值。

所以我想知道:

  1. 有没有更简单的方法(在代码中)将RGB数据输入到vpx_codec_encode中,以获得漂亮的webm视频?

  2. 我的RGB->YV12转换有问题吗?

任何帮助都将不胜感激。


1
你能告诉我你更新了代码吗?我在这里面临着完全相同的问题;-)谢谢 - user589025
2个回答

5

freefallr: 当然。这是代码。请注意,它不仅原地将RGB->YUV进行转换,还将YV12输出放入pFullYPlane/pDownsampledUPlane/pDownsampledVPlane中。我修改了vpxenc示例以使用此数据,从而生成了外观漂亮的WebM视频。

void RGB_To_YV12( unsigned char *pRGBData, int nFrameWidth, int nFrameHeight, void *pFullYPlane, void *pDownsampledUPlane, void *pDownsampledVPlane )
{
    int nRGBBytes = nFrameWidth * nFrameHeight * 3;

    // Convert RGB -> YV12. We do this in-place to avoid allocating any more memory.
    unsigned char *pYPlaneOut = (unsigned char*)pFullYPlane;
    int nYPlaneOut = 0;

    for ( int i=0; i < nRGBBytes; i += 3 )
    {
        unsigned char B = pRGBData[i+0];
        unsigned char G = pRGBData[i+1];
        unsigned char R = pRGBData[i+2];

        float y = (float)( R*66 + G*129 + B*25 + 128 ) / 256 + 16;
        float u = (float)( R*-38 + G*-74 + B*112 + 128 ) / 256 + 128;
        float v = (float)( R*112 + G*-94 + B*-18 + 128 ) / 256 + 128;

        // NOTE: We're converting pRGBData to YUV in-place here as well as writing out YUV to pFullYPlane/pDownsampledUPlane/pDownsampledVPlane.
        pRGBData[i+0] = (unsigned char)y;
        pRGBData[i+1] = (unsigned char)u;
        pRGBData[i+2] = (unsigned char)v;

        // Write out the Y plane directly here rather than in another loop.
        pYPlaneOut[nYPlaneOut++] = pRGBData[i+0];
    }

    // Downsample to U and V.
    int halfHeight = nFrameHeight >> 1;
    int halfWidth = nFrameWidth >> 1;

    unsigned char *pVPlaneOut = (unsigned char*)pDownsampledVPlane;
    unsigned char *pUPlaneOut = (unsigned char*)pDownsampledUPlane;

    for ( int yPixel=0; yPixel < halfHeight; yPixel++ )
    {
        int iBaseSrc = ( (yPixel*2) * nFrameWidth * 3 );

        for ( int xPixel=0; xPixel < halfWidth; xPixel++ )
        {
            pVPlaneOut[yPixel * halfWidth + xPixel] = pRGBData[iBaseSrc + 2];
            pUPlaneOut[yPixel * halfWidth + xPixel] = pRGBData[iBaseSrc + 1];

            iBaseSrc += 6;
        }
    }
}

我还建议阅读一下这篇文章:http://en.wikipedia.org/wiki/YUV#Y.27UV420p_.28and_Y.27V12_or_YV12.29_to_RGB888_conversion如果你不知道输入缓冲区应该有多长。 - Evren Bingøl

0

没关系。我使用的方案是正确的,但我的 U/V 降采样代码中有一个 bug。


你能发一下你的 RGB -> YUV 转换代码吗?我想看看! - user206705

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接