欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

项目记录:GPU硬解码渲染

程序员文章站 2022-07-14 18:18:28
...

项目需求

全景视频超大分辨率Zoom-in/out点播系统
单帧解码渲染版本:通过头盔位置判断是否要更换码流进行渲染,实现放大缩小效果。

  • 传统的渲染方式是:
    将硬解码得到的NV12数据拷贝回CPU内存,
    然后再将NV12格式转成YUV420格式,
    进而再调用OpenGL渲染。
    解码渲染耗时较大,卡顿,需要解决

项目记录:GPU硬解码渲染

方案

采用NVIDIA VIDEO CODEC SDK对输入8K码流进行硬解码,
使用CUDA与OpenGL互操作,
无需将数据传入CPU,将硬解码取得的NV12数据通过CUDA转成RGBA。
再进行渲染。直接用OpenGL渲染显示。

相关知识

CUDA与OpenGL互操作

OpenGL与CUDA互操作可以分成两种:

  • OpenGL将Buffer对象注册到CUDA中去,供CUDA读写操作,然后再在OpenGL中使用。一般这种情况**册的是VBO和PBO,VBO一般用于存储顶点坐标、索引等数据;PBO则一般用于存储图像数据,因此称作Pixel Buffer Object。

  • OpenGL将Texture对象注册到CUDA中去,经CUDA处理后得到纹理内容,然后在OpenGL中渲染出来。

二者的操作流程一致:
1. 在OpenGL里面初始化Buffer Object
2. 在CUDA中注册OpenGL中的Buffer Object
3. CUDA锁定资源,获取操作资源的指针,在CUDA核函数中进行处理
4. CUDA释放资源,在OpenGL中使用Buffer Object

OpenGL多线程context问题

  • 将OpenGL的Texture注册到CUDA中,需要处于正确的GL环境,
  • 而解码线程和主线程不共享同一个OpenGL Context。
  • OpenGL Context在一个时刻只能被一个线程所拥有

NV12转RGBA

具体实现

项目使用GL渲染方式是绘制顶点,贴纹理图。
所以采用GPU渲染纹理图。

GPU设置纹理图:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// 传入参数NULL
// CUDA支持的纹理格式每个元素1或2或4个通道,所以使用GL_RGBA

项目记录:GPU硬解码渲染

实现效果:

项目记录:GPU硬解码渲染