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

问题描述:

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

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; 
     } 
    } 
    } 
} 

一般我把两个U的平均值和两个V值在两个相邻行中YUYV是在YUV420的值。我只是不确定是否“平均”是做这件事的正确方法。因为我用

的ffmpeg -y -r -f 25.0 -s rawvideo 1280×720 -pix_fmt yuyv422 -i yuyv422.yuv -pix_fmt YUV420P -f rawvideo -r -s 25.0 1280x720的-v调试yuv420p.yuv

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

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

经过几次调试之后,结果是一个小问题:在分配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; 
    } 
} 

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