【问题标题】:Decode from VP8 video frame to RGB从 VP8 视频帧解码为 RGB
【发布时间】:2013-06-13 13:19:41
【问题描述】:

在我的应用程序中,我们需要在屏幕上显示视频帧。我使用 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的转换太多了。有没有设置转换函数输出帧格式的方法?

【问题讨论】:

  • 真的有人在用VP8?查看 API,我没有看到这样的选项...
  • 我不明白,你的意思:WebM其实是用VP8的。
  • 只是我的幽默感; ON2 从来没有真正通过他们的编解码器在视频市场上站稳脚跟。 VP7 刚刚消失;也许 VP8 不一样...
  • 也许 VP8 会消失。但是VP3(目前是Theora)还活着。而谷歌购买了 On2 并使用这种格式(VP8)作为标准。因此,VP8 可以活得更久,恕我直言。但是,如果一年后 VP8 会消失,我需要在我的项目中使用 webm + VP8。

标签: rgb yuv webm vp8 libvpx


【解决方案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,可以让您获得一些真正有用的核心工作和平。对此进行了测试,可以 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;
}

【讨论】:

    猜你喜欢
    • 2016-10-29
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多