OpenGL+FFmpeg实现GPU硬解码视频播放
OpenGL渲染流程
1. 着色器准备
需要准备:
- 顶点着色器代码
- 片段着色器代码
- 顶点数组
- 索引缓冲对象(IBO)数组
2. 缓冲区设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| GLuint VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO);
GLuint VBO, IBO; glGenBuffers(1, &VBO); glGenBuffers(1, &IBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
3. 着色器编译与链接
1 2 3 4 5 6 7
| program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource); program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
program.link(); program.bind();
|
4. 属性指针设置
1 2 3
| program.enableAttributeArray(0); program.enableAttributeArray(1);
|
5. 矩阵变换
1 2 3 4 5
| QMatrix4x4 model, view, projection; program.setUniformValue("model", model); program.setUniformValue("view", view); program.setUniformValue("projection", projection);
|
FFmpeg硬解码部分
1. 初始化硬解码器
1 2 3 4 5
| const AVCodec *codec = avcodec_find_decoder_by_name("h264_cuvid"); if (!codec) { codec = avcodec_find_decoder_by_name("h264_qsv"); }
|
2. 解码并传输到GPU
1 2 3 4 5 6 7 8 9
| AVFrame *frame = av_frame_alloc(); avcodec_send_packet(codecContext, packet); avcodec_receive_frame(codecContext, frame);
GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture);
|
渲染循环
1 2 3 4 5 6 7 8 9 10 11
| void paintGL() { glClear(GL_COLOR_BUFFER_BIT); program.bind(); glBindTexture(GL_TEXTURE_2D, texture); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); }
|


注意事项
-
硬解码支持:
- 需要确保GPU支持对应格式的硬解码
- 需要正确安装GPU驱动
-
性能优化:
- 使用PBO(Pixel Buffer Object)进行异步传输
- 考虑使用多重缓冲
-
同步处理:
Qt+OpenGL+FFmpeg实现GPU硬解码视频播放