将V4L2_PIX_FMT_YUYV(YUV 4:2:2)转换为V4L2_PIX_FMT_YVU420(YUV 4:2:0)

时间:2017-08-16 13:41:03

标签: c++ image-processing yuv

我一直在尝试将YUYV原始文件转换为C ++中的YUV420原始文件。格式记录在YUV Formats Page中。我的输出文件在转换后显示绿色外观。我从Experts Exchange采用了源代码,转换为YUYV而不是UYVY。这是我的源代码:

void conv422to420(uint8_t* src, uint8_t* dst)
{
  uint8_t* pyFrame = dst;
  uint8_t* puFrame = pyFrame + width_*height_; // Cb
  uint8_t* pvFrame = puFrame + width_*height_/4; // Cr

  int uvOffset = width_ * 2 * sizeof(uint8_t);

  int i,j;

  for(i=0; i<height_-1; i++)
  {
    for(j=0; j<width_; j+=2)
    {
        auto evenRow = ((i&1) == 0);
        *pyFrame++ = *src++;
        ++src;
        uint16_t calc;
        if (evenRow)
        {
            calc = *src;
            calc += *(src + uvOffset);
            calc /= 2;
            *pvFrame++ = (uint8_t) calc;
        }
        *pyFrame++ = *src++;
        ++src;
        if (evenRow)
        {
            calc = *src;
            calc += *(src + uvOffset);
            calc /= 2;
            *puFrame++ = (uint8_t) calc;
        }
    }
  }
}

通常,我将YUYV中两个相邻行中的两个U和两个V值的平均值作为YUV420中的值。我只是不确定&#34;平均它&#34;是这样做的正确方法。因为我用了

  

ffmpeg -y -r 25.0 -f rawvideo -s 1280x720 -pix_fmt yuyv422 -i yuyv422.yuv -pix_fmt yuv420p -f rawvideo -r 25.0 -s 1280x720 -v debug yuv420p.yuv

成功生成YUV420原始文件,我自己的输出文件的diff与U和Y通道中生成的ffmpeg完全不同。

所以我的问题是,有没有这种转换的开源解决方案?我的解决方案出了什么问题?

1 个答案:

答案 0 :(得分:0)

经过几次调试试验后,结果证明是一个小问题:在分配U V值后我应该增加src指针。这是代码:

uint8_t* pyFrame = dst;
uint8_t* puFrame = pyFrame + width_*height_* sizeof(uint8_t); // Cb
uint8_t* pvFrame = puFrame + width_*height_* sizeof(uint8_t)/4; // Cr

int uvOffset = width_ * 2 * sizeof(uint8_t);

int i,j;

for(i=0; i<height_-1; i++)
{
    for(j=0; j<width_; j+=2)
    {
        auto evenRow = ((i&1) == 0);
        *pyFrame++ = *src++;
        if (evenRow)
        {
            uint16_t calc = *src;
            calc += *(src + uvOffset);
            calc /= 2;
            *puFrame++ = *src;
        }
        ++src;
        *pyFrame++ = *src++;
        if (evenRow)
        {
            uint16_t calc = *src;
            calc += *(src + uvOffset);
            calc /= 2;
            *pvFrame++ = (uint8_t) calc;
        }
        ++src;
    }
}

现在我可以看到图像被正确转换了。仍不确定平均是否是最佳做法。如果有人有“最佳实践”,请告诉我。