ffmpeg cuda硬件解码后处理使用opengl渲染,全硬件流程

news/2024/11/28 17:45:12/

1 ffmpeg 硬件解码

使用硬件解码后不要transfer到内存,使用cuda转化nv12 -> bgr24
转化完毕后cuda里面存了一份bgr24

2 gpumat 和 cuda 互操作

如果需要opencv gpumat直接使用cuda内存,则可以手动构造gpumat
可以使用gpumat的各种函数

uchar3* cuda_rgb_data; // 假设这是您的CUDA内存中存储RGB数据的指针
int width, height; // 图像的宽和高
cv::cuda::GpuMat gpu_rgb(cuda_rgb_data, height, width, CV_8UC3, cudaStream_t stream = 0);
uchar3* cuda_rgb_data_r = reinterpret_cast<uchar3*>(gpu_rgb.ptr(0)); // 获取R通道指针
uchar3* cuda_rgb_data_g = reinterpret_cast<uchar3*>(gpu_rgb.ptr(1)); // 获取G通道指针
uchar3* cuda_rgb_data_b = reinterpret_cast<uchar3*>(gpu_rgb.ptr(2)); // 获取B通道指针

ptr(0)、ptr(1)和ptr(2)分别获取了R、G、B三个通道的数据指针。
使用reinterpret_cast将uchar指针转换为uchar3,便于在CUDA内核中以RGB像素的形式访问。
在CUDA内核中使用GpuMat数据:
在CUDA内核函数中,直接使用获取的CUDA指针访问GpuMat中的RGB数据。

__global__ void cuda_kernel(uchar3* cuda_rgb_data_r, uchar3* cuda_rgb_data_g, uchar3* cuda_rgb_data_b, ...)
{// 假设 blockIdx.x 和 threadIdx.x 分别表示当前线程处理的图像位置的行和列索引int row = blockIdx.x * blockDim.x + threadIdx.x;int col = blockIdx.y * blockDim.y + threadIdx.y;if (row < height && col < width) // 检查索引是否有效{// 通过指针访问GpuMat中的RGB数据uchar3 rgb_pixel = make_uchar3(cuda_rgb_data_r[row * width + col].x,cuda_rgb_data_g[row * width + col].y,cuda_rgb_data_b[row * width + col].z);// ... 使用rgb_pixel进行CUDA内核计算 ...}
}

至此,将GpuMat中的RGB数据暴露给了CUDA内核,可以直接在内核中进行访问和处理。

需要显示时,有两种方式,互操作opengl渲染,不用把cuda内存

3 cuda 与 opengl 互操作

1 首先初始化GLFW并创建一个OpenGL窗口。
2 注册并初始化一个OpenGL纹理,用于接收CUDA处理后的RGB图像数据。
3 使用CUDA-OpenGL Interop库注册这个OpenGL纹理,以便CUDA可以直接访问和写入。
4 在CUDA端,假设有一个内核cuda_process_rgb已经处理了RGB图像,并将结果存储在设备内存d_processed_img中。
5 使用cudaGraphicsMapResources、 cudaGraphicsSubResourceGetMappedArray和cudaMemcpyToArray将CUDA端的RGB图像数据复制到已注册的OpenGL纹理中。
6 在主渲染循环中,绑定纹理并使用一个简单的四边形以及相应的着色器程序来渲染纹理。
以下是示例代码,并不完整

#include <iostream>
#include <vector>
#include <GLFW/glfw3.h>
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>// CUDA kernel to process RGB image (omitted for brevity)
__global__ void cuda_process_rgb(uchar3* d_img, int width, int height);int main()
{// Initialize GLFW and create an OpenGL windowif (!glfwInit()){std::cerr << "Failed to initialize GLFW" << std::endl;return -1;}glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);GLFWwindow* window = glfwCreateWindow(800, 600, "CUDA-OpenGL Interop Example", nullptr, nullptr);if (!window){std::cerr << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);// Initialize GLEW (if needed)glewExperimental = GL_TRUE;if (glewInit() != GLEW_OK){std::cerr << "Failed to initialize GLEW" << std::endl;glfwTerminate();return -1;}// Create an OpenGL texture for renderingGLuint gl_tex;glGenTextures(1, &gl_tex);glBindTexture(GL_TEXTURE_2D, gl_tex);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// Register the OpenGL texture for CUDA-OpenGL interopcudaGraphicsResource* cuda_tex_res;cudaGraphicsGLRegisterImage(&cuda_tex_res, gl_tex, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsSurfaceLoadStore);// CUDA processing: assume you have a pre-allocated CUDA device memory buffer for the processed RGB imageuchar3* d_processed_img;cudaMalloc(&d_processed_img, width * height * sizeof(uchar3));// Call your CUDA kernel to process the image (omitted here)// cuda_process_rgb<<<...>>>(d_processed_img, width, height);// Copy the processed RGB image from CUDA to the registered OpenGL texturecudaArray* cu_array;cudaGraphicsMapResources(1, &cuda_tex_res, 0);cudaGraphicsSubResourceGetMappedArray(&cu_array, cuda_tex_res, 0, 0);cudaMemcpyToArray(cu_array, 0, 0, d_processed_img, width * height * sizeof(uchar3), cudaMemcpyDeviceToDevice);cudaGraphicsUnmapResources(1, &cuda_tex_res, 0);// Set up a simple shader program and vertex data for rendering a full-screen quad (omitted for brevity)while (!glfwWindowShouldClose(window)){glClear(GL_COLOR_BUFFER_BIT);// Bind the texture and render a full-screen quad using your shader program// ...glfwSwapBuffers(window);glfwPollEvents();}// Clean up resourcescudaFree(d_processed_img);cudaGraphicsUnregisterResource(cuda_tex_res);glDeleteTextures(1, &gl_tex);glfwTerminate();return 0;
}

总结

整个流程是一旦数据到了cuda内核,就不要轻易下载到内存,直接在cuda里面进行操作,一直到渲染完毕,后面在给出完整的代码示例


http://www.ppmy.cn/news/1418554.html

相关文章

【面经】4月9日 腾讯/csig/腾讯云/一面/1h30m

自我介绍 项目&#xff1a; 介绍项目 你这个项目和别人已有系统的项目相比&#xff0c;优势在哪里&#xff1f;如果别人系统的数据要迁到你这个系统里来&#xff0c;应该怎么做&#xff1f; 服务部署有了解吗&#xff1f;一个节点如果只能部署一个服务不是很浪费吗&#xff1f…

rocketmq面试

broker主从复制机制 同步复制&#xff1a; 等Master和Slave均写成功后&#xff0c;才反馈给客户端写成功状态&#xff1b; 如果Master出故障&#xff0c; Slave上有全部的备份数据&#xff0c;容易恢复&#xff0c;但是同步复制会增大数据写入延迟&#xff0c;降低系统吞吐量。…

今天掏心窝子!聊聊35岁了程序员何去何从?

今天的内容不聊技术&#xff0c;聊聊轻松的话题&#xff0c;脑子高速转了好几周&#xff0c;停下来思考一下人生…… 不对&#xff0c;关于35岁的问题好像也不轻松&#xff0c;些许有点沉重&#xff0c;反正不是技术&#xff0c;不用高速转动脑细胞了&#xff0c;哈哈。 兄弟…

Git 自定义命令

前言 在使用 hexo 搭建个人博客时&#xff0c;共两种部署的方法。分别为&#xff1a; 本地利用 hexo 的插件 hexo-deployer-git 来实现部署&#xff0c;缺点是需要多敲几个命令行且不方便对源码进行云端备份使用 Github Action 的 workflow 自动化部署&#xff0c;优势就是可…

韩顺平 | 零基础快速学Python(12) OOP基础

面向对象编程-基础 类与对象 类提供了把数据和功能绑定在一起的方法。创建新类时创建了新的对象类型&#xff0c;从而能够创建该类型的新实例/对象。 类时抽象的概念&#xff0c;作为数据类型代表一类事物&#xff1b;对象时具体实际的&#xff0c;作为实例代表具体事物&…

Web 题记

[极客大挑战 2019]LoveSQL 看到这种就肯定先想到万能密码&#xff0c;试试&#xff0c;得到了用户名和密码 总结了一些万能密码&#xff1a; or 11 oror admin admin-- admin or 44-- admin or 11-- admin888 "or "a""a admin or 22# a having 11# a havin…

C++中的vector容器

一. 基本概念 1. 包含在头文件 #include <vector> 2. 功能: 模拟了一个动态数组 3. 底层实现 首先开辟一定大小的数组 随着元素的增加&#xff0c;如果空间不够之后 自动采取扩容机制 -> 自增长 扩容规则&#xff1a;以原空间大小的 2 倍重新开辟一块空间 将就空…

Spring中基于事件监听驱动 和 线程池的异步任务

文章目录 事件监听驱动 与 异步事件源ApplicationContextAware接口 发布事件事件实体监听事件实现异步注入綫程池 事件驱动机制&#xff0c;与MQ消息队列比较 事件监听驱动 与 异步 事件监听驱动优点&#xff1a;解耦&#xff0c;将 事件和业务进行解耦&#xff0c;通过Asyc注解…