YUV/NV12到RGB的转换方案

CPU中的YUV转RGB

FFmpeg方案

  • FFmpeg解码默认输出YUV格式
  • 使用sws_getCachedContext进行格式转换
  • 转换目标格式为AV_PIX_FMT_RGBA
  • 适合简单场景,但CPU消耗较大
    图片1

    OpenGL中的YUV转RGB方案

方案一:RGB纹理渲染

图片1

  1. 继承关系

    1
    class PlayImage : public QOpenGLWidget, public QOpenGLFunctions_3_3_Core
  2. 初始化

    1
    2
    3
    4
    5
    void initializeGL() {
    // 创建并绑定VAO/VBO/IBO
    // 编译连接着色器程序
    // 启用顶点属性数组
    }
  3. 图像更新

    1
    2
    3
    4
    void updateImage(const QImage& image) {
    // 垂直翻转(OpenGL纹理Y轴相反)
    m_texture = new QOpenGLTexture(image.mirrored());
    }
  4. 渲染

    1
    2
    3
    4
    5
    6
    void paintGL() {
    // 绑定着色器程序
    // 绑定纹理
    // 绑定VAO
    glDrawElements(...);
    }

方案二:直接YUV渲染

图片1
图片1

  1. 数据传递
  • 直接使用AVFrame传递解码数据
  • 使用BlockingQueuedConnection确保数据安全
  1. 信号槽配置

    1
    2
    3
    4
    5
    6
    7
    // 注册AVFrame用于信号传递
    Q_DECLARE_METATYPE(AVFrame)

    // 连接信号槽
    connect(m_readThread, &ReadThread::repaint,
    playImage, &PlayImage::repaint,
    Qt::BlockingQueuedConnection);
  2. 纹理处理

    1
    2
    3
    4
    5
    6
    7
    // 三个纹理对应YUV分量
    QOpenGLTexture *m_texY, *m_texU, *m_texV;

    // 设置纹理单元
    m_program->setUniformValue("tex_y", 0);
    m_program->setUniformValue("tex_u", 1);
    m_program->setUniformValue("tex_v", 2);
  3. 渲染实现

    1
    2
    3
    4
    5
    6
    void paintGL() {
    m_texY->bind(0);
    m_texU->bind(1);
    m_texV->bind(2);
    // 执行绘制
    }

OpenGL中直接处理NV12

图片1

优势

  • 避免CPU中的格式转换
  • 性能提升约1/3
  • 直接在GPU中完成转换

实现要点

  1. 使用av_hwframe_map替代av_hwframe_transfer_data
  2. 移除sws_scale相关代码
  3. 直接返回硬件帧

格式适配

1
2
3
4
5
6
7
8
void initialize() {
// 根据输入格式选择初始化方式
if (format == AV_PIX_FMT_NV12) {
initializeNV12();
} else {
initializeYUV();
}
}

渲染流程

1
2
3
4
5
6
7
8
9
10
void paintGL() {
if (m_format == AV_PIX_FMT_NV12) {
// NV12渲染流程
bindNV12Textures();
} else {
// YUV渲染流程
bindYUVTextures();
}
// 执行绘制
}

性能对比

  1. CPU转换方案

    • 实现简单
    • CPU占用高
    • 适合简单场景
  2. OpenGL YUV方案

    • 中等复杂度
    • GPU处理
    • 性能较好
  3. OpenGL NV12方案

    • 实现较复杂
    • 性能最优
    • 适合高性能需求
      ```