You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FFmpeg中I420格式AVFrame转RGB缓冲区失败,图像异常

解决AVFrame转RGB彩色图像异常的问题

问题根源

  1. Y分量行偏移计算错误:原代码用y * width计算Y平面的行偏移,但AVFrame的linesize[0]才是Y平面每行的实际字节数(为满足内存对齐要求,linesize通常大于图像宽度),直接使用width会导致行数据错位,引发图像异常。
  2. Cr/Cb分量索引逻辑需结合linesize优化:虽然原代码Cr/Cb用了linesize,但Y分量的错误会直接导致整个图像基础错位,优先修复Y的问题。
  3. 保存图像时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 15:55:03