将 V4L2_PIX_FMT_YUYV(YUV 4:2:2) 转换为 V4L2_PIX_FMT_YVU420(YUV 4:2:0)
Convert V4L2_PIX_FMT_YUYV(YUV 4:2:2) to V4L2_PIX_FMT_YVU420(YUV 4:2:0)
我一直在尝试用 C++ 将 YUYV 原始文件转换为 YUV420 原始文件。格式记录在 YUV Formats Page. My output file shows a greenish look after conversion. I adopted the source code from 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中的值。我只是不确定 "averaging it" 是否是执行此操作的正确方法。因为我用了
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 原始文件,我自己的输出文件的差异与在 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;
}
}
现在我可以看到图像已正确转换。仍然不确定平均它是否是最好的做法。如果有人有 "best practise",请告诉我。
我一直在尝试用 C++ 将 YUYV 原始文件转换为 YUV420 原始文件。格式记录在 YUV Formats Page. My output file shows a greenish look after conversion. I adopted the source code from 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中的值。我只是不确定 "averaging it" 是否是执行此操作的正确方法。因为我用了
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 原始文件,我自己的输出文件的差异与在 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;
}
}
现在我可以看到图像已正确转换。仍然不确定平均它是否是最好的做法。如果有人有 "best practise",请告诉我。