dx11硬件解码传递给opencl并行处理

2024-05-28 15:44

本文主要是介绍dx11硬件解码传递给opencl并行处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

directx11 解码

使用ffmpeg进行directx11 解码
将解码后的NV12格式数据从D3D11 Texture中通过OpenCL处理需要经过几个步骤:首先,确保D3D11 Texture正确设置并与OpenCL上下文关联;然后,将NV12数据分两个步骤处理(Y平面和UV平面);最后,在OpenCL内核中处理这些数据。

将d3d11 texture转换成opencl对象

opencl本身是可以和dx9 dx11 等进行互操作,就是利用这一点来使用opencl来并行处理数据

bool CreateSharedSurface(void* data,  int nView, bool bIsReadOnly,cl_mem* y, cl_mem* uv)
{mfxHDLPair mid_pair = { 0 };mfxStatus sts = m_pAlloc->GetHDL(m_pAlloc->pthis, mid, reinterpret_cast<mfxHDL*>(&mid_pair));if (sts) return 0;ID3D11Texture2D *surf = (ID3D11Texture2D*)data;cl_int error = CL_SUCCESS;cl_mem memY = clCreateFromD3D11Texture2DKHR(m_clcontext, bIsReadOnly ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE,data, 0, &error);if (error) {log.error() << "clCreateFromD3D11Texture2DKHR failed. Error code: " << error << endl;return -1;}cl_mem memUV = clCreateFromD3D11Texture2DKHR(m_clcontext, bIsReadOnly ? CL_MEM_READ_ONLY : CL_MEM_READ_WRITE,data, 1, &error);if (error) {log.error() << "clCreateFromD3D11Texture2DKHR failed. Error code: " << error << endl;return -1;}*y = memY;*uv = memUV;return 0;
}

以上是转换过程

编写OpenCL内核处理NV12数据

和cuda一样,需要写核函数来处理

__kernel void processNV12(__read_only image2d_t yImage, __read_only image2d_t uvImage, __write_only image2d_t outputImage) {// 这里只是一个示例,实际处理逻辑根据需求编写int2 pos = (int2)(get_global_id(0), get_global_id(1));uchar4 yPixel = read_imageui(yImage, pos); // 读取Y平面像素uchar2 uvPixel = read_imageui(uvImage, pos / 2); // UV平面是Y的一半大小,因此坐标除以2// 这里简单地将YUV转换为RGB,实际应用中会有更复杂的处理float y = yPixel.x;float u = uvPixel.x - 128.0f;float v = uvPixel.y - 128.0f;float r = y + 1.14f * v;float g = y - 0.395f * u - 0.581f * v;float b = y + 2.032f * u;uchar4 outPixel = (uchar4)(saturate(r), saturate(g), saturate(b), 255);write_imageui(outputImage, pos, outPixel);
}

cpp执行OpenCL内核

// 假设outputImage是目标OpenCL图像对象,已根据需要创建
size_t globalWorkSize[2] = { width, height }; // width和height分别为处理图像的宽度和高度
cl_kernel kernel = clCreateKernel(program, "processNV12", &err); // program为编译好的OpenCL程序
clSetKernelArg(kernel, 0, sizeof(cl_mem), &clYImage);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &clUVImage);
clSetKernelArg(kernel, 2, sizeof(cl_mem), &outputImage);err = clEnqueueNDRangeKernel(commandQueue, kernel, 2, nullptr, globalWorkSize, nullptr, 0, nullptr, nullptr);
if (err != CL_SUCCESS) { /* 处理错误 */ }// 同步、读回数据、清理等操作

初始化过程

void initializeContextFromD3D11Device(ID3D11Device* pD3D11Device)
{
CV_UNUSED(pD3D11Device);
cl_uint numPlatforms;
cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms);
if (status != CL_SUCCESS)
CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");
if (numPlatforms == 0)
CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms");std::vector<cl_platform_id> platforms(numPlatforms);
status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL);
if (status != CL_SUCCESS)CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms");// TODO Filter platforms by name from OPENCV_OPENCL_DEVICEint found = -1;
cl_device_id device = NULL;
cl_uint numDevices = 0;
cl_context context = NULL;// try with CL_PREFERRED_DEVICES_FOR_D3D11_NV
for (int i = 0; i < (int)numPlatforms; i++)
{clGetDeviceIDsFromD3D11NV_fn clGetDeviceIDsFromD3D11NV = (clGetDeviceIDsFromD3D11NV_fn)clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11NV");if (!clGetDeviceIDsFromD3D11NV)continue;device = NULL;numDevices = 0;status = clGetDeviceIDsFromD3D11NV(platforms[i], CL_D3D11_DEVICE_NV, pD3D11Device,CL_PREFERRED_DEVICES_FOR_D3D11_NV, 1, &device, &numDevices);//CL_PREFERRED_DEVICES_FOR_D3D11_NVif (status != CL_SUCCESS)continue;if (numDevices > 0){cl_context_properties properties[] ={CL_CONTEXT_D3D11_DEVICE_NV, (cl_context_properties)pD3D11Device,CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],//CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,0};context = clCreateContext(properties, 1, &device, NULL, NULL, &status);if (status != CL_SUCCESS){clReleaseDevice(device);}else{found = i;break;}}
}
if (found < 0)
{// try with CL_ALL_DEVICES_FOR_D3D11_NVfor (int i = 0; i < (int)numPlatforms; i++){clGetDeviceIDsFromD3D11NV_fn clGetDeviceIDsFromD3D11NV = (clGetDeviceIDsFromD3D11NV_fn)clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromD3D11NV");if (!clGetDeviceIDsFromD3D11NV)continue;device = NULL;numDevices = 0;status = clGetDeviceIDsFromD3D11NV(platforms[i], CL_D3D11_DEVICE_NV, pD3D11Device,CL_ALL_DEVICES_FOR_D3D11_NV, 1, &device, &numDevices);//CL_ALL_DEVICES_FOR_D3D11_NVif (status != CL_SUCCESS)continue;if (numDevices > 0){cl_context_properties properties[] ={CL_CONTEXT_D3D11_DEVICE_NV, (cl_context_properties)pD3D11Device,CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i],//CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,0};context = clCreateContext(properties, 1, &device, NULL, NULL, &status);if (status != CL_SUCCESS){clReleaseDevice(device);}else{found = i;break;}}}if (found < 0)CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for DirectX interop");
}//cv::ocl::Context& ctx = cv::ocl::Context::getDefault(false);
//cv::ocl::initializeContextFromHandle(ctx, platforms[found], context, device);
///As you say,`initializeContextFromHandle()` symbol is not in the exported list. So I use attachContext() instead for test.
cv::ocl::attachContext("NVIDIA CUDA", platforms[found], context, device);//Test passed//return ctx;}

这篇关于dx11硬件解码传递给opencl并行处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010993

相关文章

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如

如何安装HWE内核? Ubuntu安装hwe内核解决硬件太新的问题

《如何安装HWE内核?Ubuntu安装hwe内核解决硬件太新的问题》今天的主角就是hwe内核(hardwareenablementkernel),一般安装的Ubuntu都是初始内核,不能很好地支... 对于追求系统稳定性,又想充分利用最新硬件特性的 Ubuntu 用户来说,HWEXBQgUbdlna(Har

Java向kettle8.0传递参数的方式总结

《Java向kettle8.0传递参数的方式总结》介绍了如何在Kettle中传递参数到转换和作业中,包括设置全局properties、使用TransMeta和JobMeta的parameterValu... 目录1.传递参数到转换中2.传递参数到作业中总结1.传递参数到转换中1.1. 通过设置Trans的

通过C#和RTSPClient实现简易音视频解码功能

《通过C#和RTSPClient实现简易音视频解码功能》在多媒体应用中,实时传输协议(RTSP)用于流媒体服务,特别是音视频监控系统,通过C#和RTSPClient库,可以轻松实现简易的音视... 目录前言正文关键特性解决方案实现步骤示例代码总结最后前言在多媒体应用中,实时传输协议(RTSP)用于流媒体服

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

JAVA基础:值传递和址传递

1 值传递和址传递 值传递 方法调用时,传递的实参是一个基本类型的数据 形参改变,实参不变 public static void doSum(int num1,int num2){}main(){doSum(10,20);int i = 10 ;int j = 20 ;doSum(i,j) ;}   public static void t1(int num){num = 20

六、Maven依赖管理、依赖传递和依赖冲突

1.Maven依赖管理 Maven 依赖管理是 Maven 软件中最重要的功能之一。Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题。 我们通过定义 POM 文件,Maven 能够自动解析项目的依赖关系,并通过 Maven 仓库自动下载和管理依赖,从而避免了手动

FFmpeg系列-视频解码后保存帧图片为ppm

在正常开发中遇到花屏时怎么处理呢?可以把解码后的数据直接保存成帧图片保存起来,然后直接看图片有没有花屏来排除是否是显示的问题,如果花屏,则代表显示无问题,如果图片中没有花屏,则可以往显示的方向去排查了。 void saveFrame(AVFrame* pFrame, int width, int height, int iFrame){FILE *pFile;char szFilename[

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数 一、环境说明二、页面之间相互传参 一、环境说明 DevEco Studio 版本: API版本:以12为主 二、页面之间相互传参 说明: 页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页面url找到目标页面,从而实现跳转。通过页面路由模块,可以使用不同的url访问不同的页面,包括跳转到U