FFmpeg中I420格式AVFrame转RGB缓冲区失败,图像异常
解决AVFrame转RGB彩色图像异常的问题
问题根源
- Y分量行偏移计算错误:原代码用
y * width计算Y平面的行偏移,但AVFrame的linesize[0]才是Y平面每行的实际字节数(为满足内存对齐要求,linesize通常大于图像宽度),直接使用width会导致行数据错位,引发图像异常。 - Cr/Cb分量索引逻辑需结合linesize优化:虽然原代码Cr/Cb用了linesize,但Y分量的错误会直接导致整个图像基础错位,优先修复Y的问题。
- 保存图像时wrap参数需匹配实际行字节数:确保传入
save_RGB_frame的wrap是RGB每行的实际字节数(即width*3),避免写入时行错位。
修正后的代码
修正getRGB8buffer函数
int getRGB8buffer(AVFrame* pFrame, byte* buffer){ const int width = pFrame->width, height = pFrame->height; int Y, Cr, Cb; int R, G, B; int pixel = 0; for (int y = 0; y < height; y++) { // 直接获取各平面当前行的起始指针,简化索引计算 uint8_t* y_row = pFrame->data[0] + y * pFrame->linesize[0]; uint8_t* cr_row = pFrame->data[1] + (y / 2) * pFrame->linesize[1]; uint8_t* cb_row = pFrame->data[2] + (y / 2) * pFrame->linesize[2]; for (int x = 0; x < width; x++) { Y = y_row[x]; // YUV420格式下,每2x2个Y像素对应1个Cr/Cb像素 Cr = cr_row[x / 2]; Cb = cb_row[x / 2]; YCrCb_to_RGB8(Y, Cr, Cb, R, G, B); buffer[pixel * 3 + 0] = R; buffer[pixel * 3 + 1] = G; buffer[pixel * 3 + 2] = B; pixel++; } } return 0; }
正确调用save_RGB_frame
确保传入的wrap参数为RGB每行的实际字节数(width*3):
// 调用示例 byte* rgb_buffer = new byte[width * height * 3]; getRGB8buffer(pFrame, rgb_buffer); save_RGB_frame(rgb_buffer, width * 3, width, height, "output.ppm"); delete[] rgb_buffer;
额外说明
- 确认AVFrame的像素格式为YUV420P(最常见的视频帧格式),如果是YUV422等其他格式,需调整Cr/Cb的索引逻辑。
- 原YCrCb转RGB的转换公式是正确的,无需修改。
内容的提问来源于stack exchange,提问作者hacenesh
相关产品推荐
相关产品推荐

