OpenGL与CUDA的显存数据共享
所需头文件
#include
#include "cuda_gl_interop.h"
涉及变量
cudaGraphicsResource_t cudaResource[1];//CUDA图像资源对象,用以联系OpenGL与CUDA
GLuint textureID[1];//OpenGL纹理上下文
cudaArray* devArray;//cuda共享数据区指针
操作流程
glEnable(GL_TEXTURE_2D);//开启2d上下文,告诉OpenGL要绘制的是2d的纹理
glGenTextures(1, textureID);//生成1个纹理上下文对象
glBindTexture(GL_TEXTURE_2D, textureID[0]);//绑定2d纹理上下文
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//设置2d纹理的插值方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);//生成2d纹理,对应当前的2d纹理上下文
//在CUDA中注册这2d纹理上下文,这样CUDA就知道有这么个玩意存在
cudaError_t err = cudaGraphicsGLRegisterImage(&cudaResource[0], textureID[0], GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard);
if (err != cudaSuccess)
{std::cout << "cudaGraphicsGLRegisterImage: " << err << "Line: " << __LINE__;return -1;
}
//告诉CUDA运行时映射这个共享资源
cudaGraphicsMapResources(1, cudaResource, 0);
//获得共享资源的指针,指针类型为cudaArray
cudaGraphicsSubResourceGetMappedArray(&devArray, cudaResource[0], 0, 0);
//拷贝图像数据到纹理中去
cudaMemcpyToArray(devArray, 0, 0, (void*)dpFrame, dec->GetWidth()*dec->GetHeight() * sizeof(uchar4), cudaMemcpyDeviceToDevice);
//解除锁定,让OpenGL操作
cudaGraphicsUnmapResources(1, &cudaResource[0], 0);
//可以用OpenGL在这里绘图了!
myDisplay();
示例程序
以之前这篇文章为例,可以改为OpenGL进行显示,代码如下:
#include
#include
#include "NvDecoder/NvDecoder.h"
#include "../Utils/NvCodecUtils.h"
#include "../Utils/FFmpegDemuxer.h"
#include "../Common/AppDecUtils.h"
#include "../Utils/ColorSpace.h"#include
#include "cuda_gl_interop.h"// 初始化两个Texture并绑定
cudaGraphicsResource_t cudaResource[1];
GLuint textureID[1];
cudaArray* devArray;simplelogger::Logger* logger = simplelogger::LoggerFactory::CreateConsoleLogger();void myDisplay(void)
{//将纹理映射到四边形上glBegin(GL_QUADS);//纹理的坐标和四边形顶点的对应,可以通过设置四边形的位置调整图像在窗体的位置glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 0.0);glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 0.0);glTexCoord2f(1.0, 1.0); glVertex3f(1.0, -1.0, 0.0);glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 1.0, 0.0);glEnd();glFlush();
}class HWdecode
{
public://参数对象FFmpegDemuxer *demuxer = NULL;//FFMPEG对象CUcontext cuContext;//Cuda设备NvDecoder *dec = NULL;//Cuda解码对象CUdeviceptr dpFrame = 0;//数据存储对象初始化int hwinit()//显卡设备初始化{int iGpu = 0;//选择解码播放的GPU,只有一个的话直接设置为0就行//检测硬件GPU设备ck(cuInit(0));int nGpu = 0;ck(cuDeviceGetCount(&nGpu));if (iGpu < 0 || iGpu >= nGpu){std::cout << "没有相应的GPU" << std::endl;return 0;}//获得CUDA对象CUdevice cuDevice = 0;ck(cuDeviceGet(&cuDevice, iGpu));char szDeviceName[80];ck(cuDeviceGetName(szDeviceName, sizeof(szDeviceName), cuDevice));std::cout << "GPU in use: " << szDeviceName << std::endl;ck(cuCtxCreate(&cuContext, CU_CTX_SCHED_BLOCKING_SYNC, cuDevice));return 1;}void ffmpeginit(char* url)//ffmpeg对象初始化{demuxer = new FFmpegDemuxer(url);}void cudadecoderinit()//cuda解码对象初始化{//RGBA帧存储显存初始化ck(cuMemAlloc(&dpFrame, demuxer->GetWidth() * demuxer->GetHeight() * 4));//解码器初始化dec = new NvDecoder(cuContext, (*demuxer).GetWidth(), (*demuxer).GetHeight(), true, FFmpeg2NvCodecId((*demuxer).GetVideoCodec()));}void decAndshow()//解码和播放{int nVideoBytes = 0, nFrameReturned = 0, nFrame = 0;uint8_t* pVideo = NULL, ** ppFrame;long bt = clock();do{demuxer->Demux(&pVideo, &nVideoBytes);//获取一帧视频数据 dec->Decode(pVideo, nVideoBytes, &ppFrame, &nFrameReturned);//解码这一帧数据//if (!nFrame && nFrameReturned)// LOG(INFO) << HWD.dec->GetVideoInfo();for (int i = 0; i < nFrameReturned; i++){//对解码出来的图像数据类型做转换,转到BGRAif (dec->GetOutputFormat() == cudaVideoSurfaceFormat_YUV444)YUV444ToColor32<RGBA32>((uint8_t*)ppFrame[i], dec->GetWidth(), (uint8_t*)dpFrame, 4 * dec->GetWidth(), dec->GetWidth(), dec->GetHeight());else // default assumed as NV12Nv12ToColor32<RGBA32>((uint8_t*)ppFrame[i], dec->GetWidth(), (uint8_t*)dpFrame, 4 * dec->GetWidth(), dec->GetWidth(), dec->GetHeight());//获得共享资源的指针,指针类型为cudaArraycudaGraphicsSubResourceGetMappedArray(&devArray, cudaResource[0], 0, 0);//拷贝图像数据到纹理中去cudaMemcpyToArray(devArray, 0, 0, (void*)dpFrame, dec->GetWidth()*dec->GetHeight() * sizeof(uchar4), cudaMemcpyDeviceToDevice);//解除锁定,让OpenGL操作cudaGraphicsUnmapResources(1, &cudaResource[0], 0);myDisplay();}nFrame += nFrameReturned;} while (nVideoBytes);ck(cuMemFree(dpFrame));std::cout << "Total frame decoded: " << nFrame << std::endl;std::cout << "花费时间:" << clock() - bt << "ms" << std::endl;std::cout << "FPS:" << nFrame / ((clock() - bt) / 1000.0) << std::endl;return;}
};int main(int argc, char *argv[])
{//初始化OpenGLglutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(720, 720);glutInitWindowPosition(200, 200);//创建窗口glutCreateWindow("imgshow");glEnable(GL_TEXTURE_2D);//开启2d上下文,告诉OpenGL要绘制的是2d的纹理glGenTextures(1, textureID);//生成1个2d上下文对象glBindTexture(GL_TEXTURE_2D, textureID[0]);//绑定2d上下文glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//设置2d上下文对象的插值方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);//生成2d纹理,对应当前的2d上下文//在CUDA中注册这2d上下文,这样CUDA就知道有这么个玩意存在cudaError_t err = cudaGraphicsGLRegisterImage(&cudaResource[0], textureID[0], GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard);if (err != cudaSuccess){std::cout << "cudaGraphicsGLRegisterImage: " << err << "Line: " << __LINE__;return -1;}//告诉CUDA运行时映射这个共享资源cudaGraphicsMapResources(1, cudaResource, 0);HWdecode mhwdecoder;if (!mhwdecoder.hwinit()){std::cout << "硬件初始化失败!" << std::endl;return 0;}mhwdecoder.ffmpeginit("G:\\硬解码\\3.mp4");mhwdecoder.cudadecoderinit();mhwdecoder.decAndshow();return 1;
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
