从VP8视频帧解码为RGB

时间:2013-06-13 13:19:42

标签: rgb yuv webm vp8 libvpx

在我的应用程序中,我们需要在屏幕上显示视频帧。我使用libvpx解码来自WebM的视频,但帧被解码为YUV格式(根据文档,VPX_IMG_FMT_I420)。我需要输出格式为RGB,文档说支持RGB格式的图像(VPX_IMG_FMT_RGB24)。我有一个翻译YUV-> RGB的公式:
R = Y + 1.13983 *(V-128);
G = Y - 0.39465 *(U - 128) - 0.58060 *(V - 128);
B = Y + 2.03211 *(U-128);
但我认为转换太多VP8-> YUV-> RGB。有没有为转换函数设置输出帧格式的方法?

1 个答案:

答案 0 :(得分:1)

如果你可以负担使用Intel's IPP库,这里有一些CPU友好的代码片段,你可以在你的项目中尝试和应用:

unsigned char*  mpRGBBuffer;

void VPXImageToRGB24(vpx_image_t* pImage, bool isUsingBGR)
{
   const unsigned int rgbBufferSize = pImage->d_w * pImage->d_h * 3;

   mpRGBBuffer - allocate your raw RGB buffer...

    const IppiSize  sz          = { pImage->d_w, pImage->d_h };
    const Ipp8u*    src[3]      = { pImage->planes[PLANE_Y],     pImage->planes[PLANE_U],     pImage->planes[PLANE_V]       };
    int             srcStep[3]  = { pImage->stride[VPX_PLANE_Y], pImage->stride[VPX_PLANE_U], pImage->stride[VPX_PLANE_V]   };

    if (isUsingBGR) ippiYCbCr420ToBGR_8u_P3C3R(src, srcStep, pDest, pImage->d_w * 3, sz);
    else            ippiYCbCr420ToRGB_8u_P3C3R(src, srcStep, pDest, pImage->d_w * 3, sz);
}

如果你不想使用IPP,那么a link对于一些真正有用的核心工作和平而言{{3}}。经测试,100%但不确定CPU成本。

以下是上述链接中的代码(如果链接失败...)

inline int clamp8(int v)
{
    return std::min(std::max(v, 0), 255);
} 

Image VP8Decoder::convertYV12toRGB(const vpx_image_t* img)
{
    Image rgbImg(img->d_w, img->d_h);
    std::vector<uint8_t>& data = rgbImg.data;

    uint8_t *yPlane = img->planes[VPX_PLANE_Y];
    uint8_t *uPlane = img->planes[VPX_PLANE_U];
    uint8_t *vPlane = img->planes[VPX_PLANE_V];

    int i = 0;
    for (unsigned int imgY = 0; imgY < img->d_h; imgY++) {
        for (unsigned int imgX = 0; imgX < img->d_w; imgX++) {
            int y = yPlane[imgY * img->stride[VPX_PLANE_Y] + imgX];
            int u = uPlane[(imgY / 2) * img->stride[VPX_PLANE_U] + (imgX / 2)];
            int v = vPlane[(imgY / 2) * img->stride[VPX_PLANE_V] + (imgX / 2)];

            int c = y - 16;
            int d = (u - 128);
            int e = (v - 128);

            // TODO: adjust colors ?

            int r = clamp8((298 * c           + 409 * e + 128) >> 8);
            int g = clamp8((298 * c - 100 * d - 208 * e + 128) >> 8);
            int b = clamp8((298 * c + 516 * d           + 128) >> 8);

            // TODO: cast instead of clamp8

            data[i + 0] = static_cast<uint8_t>(r);
            data[i + 1] = static_cast<uint8_t>(g);
            data[i + 2] = static_cast<uint8_t>(b);

            i += 3;
        }
    }
    return rgbImg;
}